//============================================================================================
/**
 * @file	pkthln_hurdle.c
 * @brief	ポケスロン競技：ハードル走
 * @author	Nozomu Saito
 */
//============================================================================================

#include "common.h"
#include "../../pkthln_obj_common.h"
#include "../../poke_clact.h"
#include "pkthln_hurdle.h"
#include "system/wipe.h"
#include "system/render_oam.h"
#include "system/fontproc.h"
#include "gflib/touchpanel.h"
#include "../../pkthln_comm_pack.h"
#include "../../poke_clact_move.h"

#include "system/arc_util.h"

#include "../pkthln_clact.h"

#include "h_obst_generate.h"
#include "h_obst.h"
#include "h_smog_generate.h"

#include "../hit_rect.h"

#include "hurdle_poke_icon.h"

#include "system/snd_tool.h"
#include "../event_se_def.h"

#include "../pkthln_act_def.h"

#include "hurdle_comm.h"

#include "hurdle_obj_pri.h"
#include "../../cmn_res.h"
#include "../../pkthln_poke_act.h"

#include "pkthln_hurdle_cmn_def.h"

//成績作成用
#include "system/msgdata_util.h"
#include "msgdata/msg.naix"
#include "msgdata/msg_pokethlon.h"

#include "pkthev_dash.naix"
#include "../pkthln_evt_info.naix"

#include "communication/wm_icon.h"

// 構造体が想定のサイズとなっているかチェック
#ifdef PM_DEBUG
#ifdef _NITRO
SDK_COMPILER_ASSERT(sizeof(HURDLE_PARENT_DATA) == 36);
#endif
#endif

#define DASH_HEAP_SIZE	(0x48000)

#define HURDLE_EVENT_POKE_NUM	(3)
#define TOTAL_POKE_NUM	( ENTRY_MEMBER_NUM_MAX*HURDLE_EVENT_POKE_NUM )
#define OBST_MAX		(OBST_NUM * HURDLE_EVENT_POKE_NUM)

#define HURDLE_EVENT_PAL_NUM	(HURDLE_EVENT_POKE_NUM+1+1+12+1)
//↑ポケモン+障害物競走OBJパレット+時計パレット+アイコン12+共通リソース

#define START_LINE_OFS	(416)		//縦512キャラスクリーンのスタートライン底辺オフセット

#define GOAL_LINE_OFS	(START_LINE_OFS+3*8)	//最終的にフィルするゴールラインの位置

#define PCLACT_TCB_PRIORITY	(0)
#define ARRAY_BASE_Y	(64)
#define ARRAY_BASE_X	(32)
#define DRAW_OFS_X_S	(16)
#define DRAW_OFS_X_L	(32)

#define RANE1_POKE_X	(48)
#define RANE2_POKE_X	(128)
#define RANE3_POKE_X	(208)

#define RANE_POKE_Y		(/*112-16*/15*8)

#define BG_START_OFS	(128-DISP_BLANK)		//上下画面にDISP_BLANKドットのブランク空間がある
#define MS_BG_OFS		(192+DISP_BLANK)		//上下画面にDISP_BLANKドットのブランク空間がある

#define	LANE_LENGTH		(4096)
#define INV_TIME		(4)

#define	HIDE_OFS		(16)

#define OBST_PALETTE_NUM	(1)
#define BOOST_PALETTE_NUM	(1)
#define RANK_PALETTE_NUM	(1)
#define WATCH_PALETTE_NUM	(1)

#define TIMER_ACT_NUM	(6)

#define SMOG_NUM	(SMOG_STACK_NUM * LANE_NUM)

#define ACT_MAX	( (OBST_MAX*2) + 1+1+1+1+ (HURDLE_EVENT_POKE_NUM*7)+1+TIMER_ACT_NUM+(12*3)+SMOG_NUM )
//↑障害物12*2+カウントダウン1+ラストカウント+ニューレコード1+旗1+(ポケ+影+マーカー+順位+ジャンプ+ブースト+ペン)*3+時計1+時間表示6 + (アイコン+アイコンマーカ+アイコン順位)12+土煙スタック5*レーン数

#define HURDLE_EVENT_OBJ_NUM	(ACT_MAX)

#define COUNT_MAX		(90)

#define SHADOW_POS_OFS	(8)
#define LANE_INFO_WIDTH	(224)	//レース状況表示幅	256-(16+16)


#define PENALTY_SPEED	(0.5)

#define GOAL_AF_SPEED	(1)

#define SPIN_WAIT	(4)

#define SUB_DISP_WIDTH	(256)	//サブ画面幅
#define DISP_PIVOT	(64)		//相対表示基点座標
#define SUB_DISP_LENGTH	(512)			//位画面の距離幅

#define GOAL_FINISH_LEN		(128)		//ゴールしてからどれくらい走るか(この辺は適当)

#define GOAL_AFTER_POS	(RANE_POKE_Y)

//OBJのBGプライオリティ
#define MAIN_OBJ_BG_PRI	(1)
#define SUB_OBJ_BG_PRI	(0)

#define BOOST_MAX	(4)
#define SPEED_MAX	(10.0)
#define BOOST_SPACE	(24)		//ブーストジャンプ成功ドット幅
#define START_SPEED	(1.0)
#define GOAL_SPEED	(START_SPEED)

#define PENALTY_TIME	(30)
#define RANK_DISP_POS	(MS_BG_OFS+156)
#define GOAL_RANK_DISP_POS	(MS_BG_OFS+40)
#define GOAL_ANM_OFS	(TOTAL_POKE_NUM)	//セル依存

#define SMOG_PENALTY_FRAME	(24)
#define SMOG_FRAME1	(8)
#define SMOG_FRAME2	(6)
#define SMOG_FRAME3	(6)
#define SMOG_FRAME4	(6)
#define SMOG_FRAME5	(4)

//ＢＭＰ関連
#define	REC_FONT_PAL	(15)
#define WIN_CGX_BASE	(1)
#define WIN_REC_CGX	(WIN_CGX_BASE)
#define REC_BG	(GF_BGL_FRAME3_M)

#define	COL_N_WHITE	( GF_PRINTCOLOR_MAKE( 15, 14, 0 ) )		// フォントカラー：白

#define WATCH_X	(20*8)
#define WATCH_Y	(23*8)
#define TIMER_ACT_POS_X	(22*8)
#define TIMER_ACT_POS_Y	(23*8)

#define DRAW_RANK_FRAME		(30)		//順位描画更新タイミング
#define FIRST_DRAW_RANK_FRAME		(150)		//初回順位描画更新タイミング

#define DOUBLE_JUMP_START_FRAME	(3)		//２段ジャンプ開始フレーム
#define DBL_JUMP_FRAME	(5)			//２段ジャンプ許可フレーム

#define NPC_PROB_TYPE_NUM	(6)	//NPCのジャンプ確率パターン数

#include "hurdle_jump.dat"	//BOOST_MAXの定義後におく

#define TOUCH_W	(6*8)
#define TOUCH_H	(80)
#define TOUCH_Y	(11*8)

static u8 SndPlayer[HURDLE_EVENT_POKE_NUM] = {
	PLAYER_SE_1,
	PLAYER_SE_2,
	PLAYER_SE_3,
};
static s8 SndPan[HURDLE_EVENT_POKE_NUM] = {
	-108, 0, 107
};

typedef struct TOUCH_REQ_tag
{
	int Lane;
	int Y;
}TOUCH_REQ;

typedef struct H_LOCAL_ST_tag
{
	int St;
	u8 Count;
	u8 SpinCount;
	u8 SpinDir;
	u8 dummy;
	int bf_jump_x;
	int bf_jump_y;
}H_LOCAL_ST;

typedef struct HURDLE_POKE_PARAM_tag
{
	float BaseSpeed;
	float AcceleSpeed;
	u8 JumpLv;
	u8 dummy[3];

	u16 UpDownFrame;
	u16 FlyFrame;
}HURDLE_POKE_PARAM;

typedef struct HURDLE_POKE_tag
{
	POKE_ACT_PTR	PokeActPtr;		//ポケモンアクター
	int State;		//ジャンプ中とか、加速中とか

	H_LOCAL_ST	LST;		//ローカルステート
	int RunPos;		//ポケモンの位置（アクターの値だとジャンプ値も入ってしまうので）
	int ShiftEffPos;
	PKTHLN_ACT_PTR ShiftPtr;
	PKTHLN_ACT_PTR RankPtr;
	PKTHLN_ACT_PTR BoostPtr;

	HURDLE_POKE_PARAM	PokeParam;

	u16 DoubleJump;		//２段ジャンプフラグ
	u16 DblJumpTouchNum;	//降下中のタッチ回数

}HURDLE_POKE;

typedef struct TIMER_tag
{
	PKTHLN_ACT_PTR Watch;
	CLACT_WORK_PTR Number[TIMER_ACT_NUM];	//分1桁、秒2桁、小数1桁、コロン1　カンマ1
}TIMER;

typedef struct HURDLE_LANE_tag
{
	u16 RunLength;		//走行距離
	u16 Time;
	u16 S_BGOffset;		//上画面BGオフセット
	u16 M_BGOffset;		//下画面BGオフセット

	u8 Finished;		//ゴールしたか？
	u8 Boost;			//現在のブースト状況　0〜BOOST_MAX
	u8 dummy[2];

	float SpeedF;			//現在のスピード（小数点以下有効）
	float RestSpeed;		//小数点以下の数字管理用

	u16 MainFrameNo;
	u16 SubFrameNo;

	u8 LaneNo;			//レーン番号
	u8 FillCount;
	u8 OldFillPoint;
	u8 FillPoint;

	int ScrTransState;

	H_OBST_PTR	ObstArray;
	HURDLE_POKE	DashPoke;

	float RankScale;
	s16 LocalRank;
	u16 SmogCounter;

}HURDLE_LANE;
/**
typedef struct NPC_DATA_tag
{
	int Len;
	int Time;
	BOOL Finish;
}NPC_DATA;
*/
typedef struct NPC_DATA_CORE_tag
{
	u8 State;
	u8 Counter;
	u8 Boost;
	u8 Grate;
	u8 Bad;
	u8 dummy[3];
	float SpeedF;
	float RestSpeed;
	float BaseSpeed;
	float AcceleSpeed;
	BOOL Finished;
	int Time;
	int RunLen;
	int CheckPos;
}NPC_DATA_CORE;

typedef struct PKTHLN_HURDLE_tag
{
	int HeapID;
	GF_BGL_INI *bgl;
	GF_BGL_BMPWIN	Win;			// BMPウィンドウデータ
///	PCLACT_CNT_PTR PclActCntPtr;	//ポケモンアクターコントローラポインタ
	HURDLE_POKE Poke[HURDLE_EVENT_POKE_NUM];
	//障害物ジェネレーター
	H_OBST_GENERATE_PTR		ObstGenePtr;
	//土煙ジェネレーター
	H_SMOG_GENE_PTR		SmogGenePtr;
	//走行レーン管理
	HURDLE_LANE	Lane[HURDLE_EVENT_POKE_NUM];

	//アクター
	PKTHLN_CLACT_CNT_PTR ActCntPtr;

	//ポケモンアイコン
	HPI_CNT_PTR HpiCntPtr;
	//全ポケ位置情報
///	COMM_DATA_PACK CommDataPack;
	//時間
	u32	MyTime;			//<<こっちは自分のポケがゴールするととまる
	u32	GameTime;		//<<こっちはずっとカウントし続ける
	u32 StartCount;

	NPC_DATA_CORE NpcData[9];

///	PKTHLN_ACT_PTR GoalFlag;

	CMN_RES_CNT_PTR	CmnResCntPtr;
	POKE_ACT_CNT_PTR PokeActCntPtr;

	TIMER Timer;

	u16 DrawRankFrame;
	u8 FirstDrawFlg;
	u8 DrawCounterStart;

}PKTHLN_HURDLE;

typedef struct HURDLE_PARAM_tag
{
	int UpDown[5];
	int Fly[5];
	int Accele[5];
	int Speed[5];
}HURDLE_PARAM;

typedef struct ITEM_tag
{
	u16 Rank;
	u16 Index;
}ITEM;

typedef  struct NODE_tag NODE;

typedef struct NODE_tag
{
	NODE *Prev;
	NODE *Next;
	ITEM Item;
}NODE;

typedef struct R_ITEM_tag
{
	u16 Len;
	u16 Index;
	u16 Time;
	u16 Goal;
	BOOL TakingOver;
}R_ITEM;

typedef  struct R_NODE_tag R_NODE;

typedef struct R_NODE_tag
{
	R_NODE *Prev;
	R_NODE *Next;
	R_ITEM Item;
}R_NODE;

typedef struct RANK_ARRAY_tag
{
	u16 Idx;
	u16 Rank;
}RANK_ARRAY;

enum{
	D_POKE_ST_NONE,
	D_POKE_ST_JUMP,
	D_POKE_ST_PENALTY_DOWN,
	D_POKE_ST_GOAL_MOVE,
	D_POKE_ST_FINISHED,
};

enum{
	LST_NONE,
	LST_JUMP_UP,
	LST_JUMP_KEEP,
	LST_JUMP_DOWN,
	LST_PENALTY,
};

enum{
	FINISH_NONE,
	FINISH_GOAL,
};

enum {
	NONE_BOOST,
	BOOST_LV234,
	BOOST_LV5
};

enum {
	NO_BOOST = 0,
	BOOST1,
	BOOST2,
	BOOST3,
	BOOST4,
};

//タイマーアクターアニメ番号（セルアニメデータ依存）
static const u8 DefaultTimerActAnm[TIMER_ACT_NUM] = {
	1,12,1,1,11,1,				//○，○○，○を表示
};
//タイマーアクターX座標
static const u8 TimerActPosX[TIMER_ACT_NUM] = {
	TIMER_ACT_POS_X, TIMER_ACT_POS_X+8, TIMER_ACT_POS_X+24, TIMER_ACT_POS_X+40,
	TIMER_ACT_POS_X+48, TIMER_ACT_POS_X+64,
};

static void SetVramBank(void);

static BOOL HURDLE_Func_Phase1(PKTHLN_PTR work, u8 *seq);
static BOOL HURDLE_Func_Phase2(PKTHLN_PTR work, u8 *seq);
static BOOL HURDLE_Func_Phase3(PKTHLN_PTR work, u8 *seq);

static void InitBG(GF_BGL_INI * ini);
static void SetBGChar(GF_BGL_INI * ini, const int inHeapID);
static void LoadBG(GF_BGL_INI * ini, const int inHeapID);

static BOOL LaneCntMain(PKTHLN_PTR work, PKTHLN_HURDLE_PTR ptr);
static void SetUpLane(PKTHLN_PTR work, const HURDLE_PARAM *inData, EVT_HIT_DATA *inHitData,
		H_OBST_GENERATE_PTR pGenePtr, PKTHLN_CLACT_CNT_PTR pActCntPtr, POKE_ACT_CNT_PTR pPokeActCntPtr,
		const u8 inLaneIdx, HURDLE_LANE *outLane);
static H_OBST_PTR LANE_GetObstPtr(HURDLE_LANE *inLane, const int inIdx);
static void LaneMain(PKTHLN_PTR work, PKTHLN_HURDLE_PTR ptr, HURDLE_LANE *inLane, const TOUCH_REQ *inTouchReq);

static void DashPokeMove(const u8 inLaneIdx, HURDLE_POKE *outDashPoke, float *outSpeed);
static void DashPokeSetState(PKTHLN_PTR work, const int inY, const u8 inIdx, HURDLE_POKE *ioDashPoke);

static BOOL CheckHit(const int inY, const u8 inRange, const HIT_RECT *inRect);
static BOOL CheckBoost(const int inY, const HIT_RECT *inRect);
static void TransScreen(GF_BGL_INI *bgl, HURDLE_LANE *ioLane);
static void PositionCont(PKTHLN_HURDLE_PTR ptr, HURDLE_PARENT_DATA *parent);
static void SetDraw(PKTHLN_PTR work);
static void CalcRank(PKTHLN_PTR work);
static BOOL SortTime(R_NODE *now, R_NODE *target);
static BOOL SortLen(R_NODE *now, R_NODE *target);
static void SetRankToCommData(HURDLE_PARENT_DATA *parent, const u8 inIdx, const u8 inRank);
static void CommMain(PKTHLN_PTR work);
static void MoveNPC(PKTHLN_PTR work);

static BOOL CheckGoalMoveEnd(PKTHLN_HURDLE_PTR ptr);
static void GenerateObst(PKTHLN_HURDLE_PTR ptr, const int inLength, const u8 inLane);
static void GenerateSmog(PKTHLN_HURDLE_PTR ptr, HURDLE_LANE *ioLane);

static u8 CheckPokeTouch(PKTHLN_HURDLE_PTR ptr, const u16 inX, const u16 inY);

static void CreateBmpWin( PKTHLN_HURDLE_PTR ptr );
static void SetRecordStr(PKTHLN_HURDLE_PTR ptr, const int inTime);

static void SetPokeScale(HURDLE_POKE *outDashPoke, const int inYOfs);
static void SetNonJmpPokeScale(HURDLE_POKE *outDashPoke, const u8 inFlg);
static void DispTime(PKTHLN_HURDLE_PTR ptr);

static void MoveNPCCore(PKTHLN_PTR work, PKTHLN_HURDLE_PTR ptr, HURDLE_CHILD_DATA *child,
						const u8 inNetID, const u8 inLane, const u8 inDataIdx);
static void MakeNPCCoreData(PKTHLN_PTR work, const HURDLE_PARAM* inData);

static void Boost(PKTHLN_PTR work, HURDLE_LANE *inLane);

static void CountTime(PKTHLN_HURDLE_PTR ptr);

static int FixTime(int inTime);

PKTHLN_FUNC HurdleFuncTbl[] = {
	HURDLE_Func_Phase1,
	HURDLE_Func_Phase2,
	HURDLE_Func_Phase3,
};

enum {
	DASH_SEQ_PHASE1,
	DASH_SEQ_PHASE2,
	DASH_SEQ_PHASE3,
};

//----------------------------------------------------------------------------
/**
 *	@brief	メインシーケンス関数
 *
 *	@param	work		ポケスロンポインタ
 *	@param	*seq		シーケンサ
 *
 *	@return	TRUE
 */
//-----------------------------------------------------------------------------
static BOOL HURDLE_Func_Phase1(PKTHLN_PTR work, u8 *seq)
{
	OS_Printf("画面が出ましたよ。とくになにもしなくてよいかしら？\n");
	//シーケンスシフト
	PTFrame_SetNextFuncTblIdx(work, DASH_SEQ_PHASE2);
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	メインシーケンス関数
 *
 *	@param	work		ポケスロンポインタ
 *	@param	*seq		シーケンサ
 *
 *	@return	TRUE
 */
//-----------------------------------------------------------------------------
static BOOL HURDLE_Func_Phase2(PKTHLN_PTR work, u8 *seq)
{
	BOOL rc;
	PKTHLN_HURDLE_PTR ptr = PTFrame_GetEventWorkPtr(work);

	switch(*seq){
	case 0:	//カウント
		if ( PTFrame_CountDown(work) ){
			//カウントダウン終了後、順位描画カウンターをカウント開始
			ptr->DrawCounterStart = 1;
			(*seq)++;
		}
		break;
	case 1:
#ifdef PM_DEBUG
		//終了テスト
		if (sys.trg & PAD_BUTTON_X){
			PTFrame_SetNextFuncTblIdx(work, DASH_SEQ_PHASE3);
			return FALSE;
		}
#endif
		CountTime(ptr);
		rc = LaneCntMain(work, ptr);
		//NPC動作
		MoveNPC(work);
		if (rc){
			int time;
			u8 i;

			time = 0;
			for(i=0;i<ENTRY_MAX;i++){
				time += ptr->Lane[i].Time;
			}
			//フレームワークにニューレコードチェック用のレコード値をセット
			PTFrame_SetCheckRecord(work, time);
			SetRecordStr(ptr, time);
			(*seq)++;
		}

		break;
	case 2:
		{
			u8 end_check = 0;
			end_check = PTFrame_DispEnd(work);
			if ( CheckGoalMoveEnd(ptr)&&end_check ){
				//エンド非表示
///				CLACT_SetDrawFlag(ptr->CDActPtr, 0);
				(*seq)++;
			}
			CountTime(ptr);
			LaneCntMain(work, ptr);
			//NPC動作
			MoveNPC(work);
		}
		break;
	case 3:	//全員のゴール待ちシーケンス
		CountTime(ptr);
		//NPC動作
		MoveNPC(work);
		//通信データに終了をセット
		{
			HURDLE_CHILD_DATA *child_data;
			COMM_EVENT_COMMON_DATA *data;
			data = PTFrame_GetEvtComCmnData(work);
			child_data = PKTHLN_CommPack_GetData(&data->SendData);
			child_data->Finish = 1;
		}

		{
			COMM_EVENT_COMMON_DATA *data = PTFrame_GetEvtComCmnData(work);
			HURDLE_PARENT_DATA *parent = PKTHLN_CommPack_GetData(&data->ReciveShareData);
			if (parent->Finish){
				OS_Printf("親が終了許可\n");
				//全員ゴール
				(*seq)++;
				ptr->StartCount = 0;
			}
		}
		break;
	case 4:	//終了カウント
		ptr->StartCount++;
		if (ptr->StartCount > COUNT_MAX){
			//フェードアウトリクエスト
			WIPE_SYS_Start(	WIPE_PATTERN_WMS, WIPE_TYPE_FADEOUT,
							WIPE_TYPE_FADEOUT, WIPE_FADE_BLACK,
							WIPE_DEF_DIV, WIPE_DEF_SYNC, ptr->HeapID );
			//シーケンスシフト
			PTFrame_SetNextFuncTblIdx(work, DASH_SEQ_PHASE3);
		}
		break;
	}

	//通信関連
	CommMain(work);

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	結果シーケンス関数
 *
 *	@param	work		ポケスロンポインタ
 *	@param	*seq		シーケンサ
 *
 *	@return	TRUE
 */
//-----------------------------------------------------------------------------
static BOOL HURDLE_Func_Phase3(PKTHLN_PTR work, u8 *seq)
{
	int time;
	int net_id;
	PKTHLN_HURDLE_PTR ptr = PTFrame_GetEventWorkPtr(work);

	if (*seq == 0){
		//フェードアウト待ち
		if ( WIPE_SYS_EndCheck() ){
			*seq = 1;
		}
		return FALSE;
	}

	net_id = PTFrameGetCurrentID(work);
	//結果セット
	{
		int i;
		time = 0;
		for(i=0;i<ENTRY_MAX;i++){
			time += ptr->Lane[i].Time;
		}
		OS_Printf("合計タイム:%d\n",time);
		//少数第一位までしか記録に残せないので、第2位以下の部分を切る
		time = FixTime(time);
		PTFrame_SetEvtResultOrg(work, net_id, time);
	}

	//親の場合、NPCの結果をここでセット
	if (net_id == COMM_PARENT_ID){
		int i,j;
		int player_num = PTFrame_GetPlayerNum(work);
		for(i=player_num;i<ENTRY_MEMBER_NUM_MAX;i++){
			time = 0;
			for(j=0;j<ENTRY_MAX;j++){
				int idx;
				idx = (i-player_num)*ENTRY_MAX+j;
				//ゴールしていないNPCはタイムを作成
				if (!ptr->NpcData[idx].Finished){
					//残り距離を時間に変更し、タイムに加算
					float temp;
					float f_temp;
					int i_temp;
					float spd;
					spd = ptr->NpcData[idx].SpeedF;
					if (spd < ptr->NpcData[idx].BaseSpeed){
						spd = ptr->NpcData[idx].BaseSpeed;
					}
					temp = (float)(LANE_LENGTH - ptr->NpcData[idx].RunLen)/spd;
					f_temp = temp;
					i_temp = f_temp;
					f_temp = f_temp-(float)i_temp;
					if (f_temp > 0){
						//小数点がある
						i_temp+=1;	//少数切り上げ
					}
					ptr->NpcData[idx].Time = ptr->GameTime + i_temp;
				}
				time += ptr->NpcData[idx].Time;
			}	//end for
			//少数第一位までしか記録に残せないので、第2位以下の部分を切る
			time = FixTime(time);
			PTFrame_SetEvtResultOrg(work, i, time);
			OS_Printf("合計タイム:%d\n",time);
		}	//end for
	}

	OS_Printf("結果計算関数へ。\n");
	return TRUE;
}

//--------------------------------------------------------------------------------------------
/**
 * 初期化関数
 *
 * @param	work		ポケスロンワークポインタ
 * @param	*pParam		パラメータ
 *
 * @return	TRUE
 */
//--------------------------------------------------------------------------------------------
PTH_RC PE_HURDLE_InitFunc(PKTHLN_PTR work, void *pParam)
{
	PKTHLN_HURDLE_PTR ptr = PTFrame_GetEventWorkPtr(work);
	u8 seq = PTFrame_GetSubSeq(work);
	switch(seq){
	case 0:
		{
			int heap_id;
			sys_CreateHeap( HEAPID_POKETHLON, HEAPID_PT_DASH, DASH_HEAP_SIZE );
			heap_id = HEAPID_PT_DASH;
///			sys_PrintHeapExistMemoryInfo( heap_id );

			sys_VBlankFuncChange( NULL, NULL );	// VBlankセット
			sys_HBlankIntrSet( NULL,NULL );		// HBlankセット

			GF_Disp_GX_VisibleControlInit();
			GF_Disp_GXS_VisibleControlInit();
			GX_SetVisiblePlane( 0 );
			GXS_SetVisiblePlane( 0 );

			//VRAMバンク割り当て
			SetVramBank();
			//アプリケーションメモリー
			ptr = PTFrame_AllocEventWork(work, sizeof(PKTHLN_HURDLE));
			MI_CpuClear8( ptr, sizeof(PKTHLN_HURDLE));

			//BGLアロケーション
			ptr->bgl = GF_BGL_BglIniAlloc(heap_id);

			//ジェネレータ初期化
			ptr->ObstGenePtr = H_OBST_GENE_Init(ptr->HeapID);
			ptr->SmogGenePtr = H_SMOG_GENE_Init(ptr->HeapID);

			//競技アプリ内共有データポインタのセット
			PTFrame_SetEvtShareDataPtr(work,
					H_OBST_GENE_GetObstSendDataPtr(ptr->ObstGenePtr),
					H_OBST_GENE_GetObstDataPtr(ptr->ObstGenePtr),
					H_OBST_GENE_GetObstDataSize(ptr->ObstGenePtr) );

			//レコード表示ＢＧのセット
			PTFrame_SetRecBGMask(work, GX_PLANEMASK_BG3);

			{
				CHAR_MANAGER_MAKE cm;
				cm.CharDataNum = HURDLE_EVENT_OBJ_NUM;
				cm.VramTransAreaMain = 256*1024;
				cm.VramTransAreaSub = 16*1024;
				cm.heap = heap_id;

				//キャラ・パレットマネージャ初期化
				PKTHLN_OBJ_COMMON_InitCharPlttManager(	&cm,
														HURDLE_EVENT_PAL_NUM,
														heap_id,
														GX_OBJVRAMMODE_CHAR_1D_256K,
														GX_OBJVRAMMODE_CHAR_1D_256K);
			}

			// OAMマネージャーの初期化
			NNS_G2dInitOamManagerModule();

			// 共有OAMマネージャ作成
			// レンダラ用OAMマネージャ作成
			// ここで作成したOAMマネージャをみんなで共有する
			REND_OAMInit(
					0, 126,		// メイン画面OAM管理領域
					0, 32,		// メイン画面アフィン管理領域
					0, 126,		// サブ画面OAM管理領域
					0, 32,		// サブ画面アフィン管理領域
					heap_id);
			ptr->HeapID = heap_id;
		}

		//タッチフォントロード
		FontProc_LoadFont(FONT_TOUCH, ptr->HeapID);

		//BG初期化
		InitBG(ptr->bgl);

		CreateBmpWin( ptr );

		//下画面をメインにする
		sys.disp3DSW = DISP_3D_TO_SUB;
		GF_Disp_DispSelect();

		//次のシーケンスへ
		PTFrame_IncSubSeq(work);
		break;
	case 1:
		{
			int i;

			PKTHLN_ACT_SETUP_PRM param = {
				ACT_MAX,6,{6,6,6,6}
			};

			//アクター関連
			ptr->ActCntPtr = PkthlnClAct_Init(ptr->HeapID, &param);


			//上下画面幅設定
			PkthlnClAct_SetDispDistance(ptr->ActCntPtr,
										0, (MS_BG_OFS*FX32_ONE),
										0, 0 );

			PkthlnClAct_SetResObjCode(ptr->ActCntPtr, 0, RES_CODE_OBST);
			PkthlnClAct_SetResObjCode(ptr->ActCntPtr, 1, RES_CODE_BJUMP);
			PkthlnClAct_SetResObjCode(ptr->ActCntPtr, 2, RES_CODE_OBST_BREAK);
			PkthlnClAct_SetResObjCode(ptr->ActCntPtr, 3, RES_CODE_RANK);
			PkthlnClAct_SetResObjCode(ptr->ActCntPtr, 4, RES_CODE_BOOST);
			PkthlnClAct_SetResObjCode(ptr->ActCntPtr, 5, RES_CODE_BWATCH);

			//障害物競走用OBJ
			PkthlnClAct_SetChar( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_obj_h_NCGR,
							RES_CODE_OBST, NNS_G2D_VRAM_TYPE_MAX);
			PkthlnClAct_SetPaltt( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_obj_h_NCLR,
							RES_CODE_OBST, NNS_G2D_VRAM_TYPE_MAX, OBST_PALETTE_NUM	);
			PkthlnClAct_SetCell( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_obj_h_NCER,
							RES_CODE_OBST	);
			PkthlnClAct_SetAnm(	ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_obj_h_NANR,
							RES_CODE_OBST	);
			//ジャンプエフェクト
			PkthlnClAct_SetChar( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_obj_eff01_NCGR,
							RES_CODE_BJUMP, NNS_G2D_VRAM_TYPE_2DMAIN);
			PkthlnClAct_SetPaltt( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_obj_eff01_NCLR,
							RES_CODE_BJUMP, NNS_G2D_VRAM_TYPE_2DMAIN, BOOST_PALETTE_NUM	);
			PkthlnClAct_SetCell( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_obj_eff01_NCER,
							RES_CODE_BJUMP	);
			PkthlnClAct_SetAnm(	ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_obj_eff01_NANR,
							RES_CODE_BJUMP	);
			//障害物ぶっ壊れ
			PkthlnClAct_SetChar( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_obj_h_main_NCGR,
							RES_CODE_OBST_BREAK, NNS_G2D_VRAM_TYPE_2DMAIN);
			PkthlnClAct_SetPaltt( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_obj_h_NCLR,
							RES_CODE_OBST_BREAK, NNS_G2D_VRAM_TYPE_2DMAIN, OBST_PALETTE_NUM	);
			PkthlnClAct_SetCell( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_obj_h_main_NCER,
							RES_CODE_OBST_BREAK	);
			PkthlnClAct_SetAnm(	ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_obj_h_main_NANR,
							RES_CODE_OBST_BREAK	);
			//ブーストエフェクト
			PkthlnClAct_SetChar( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_obj_eff02_NCGR,
							RES_CODE_BOOST, NNS_G2D_VRAM_TYPE_2DMAIN);
			PkthlnClAct_SetPaltt( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_obj_eff02_NCLR,
							RES_CODE_BOOST, NNS_G2D_VRAM_TYPE_2DMAIN, BOOST_PALETTE_NUM	);
			PkthlnClAct_SetCell( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_obj_eff02_NCER,
							RES_CODE_BOOST	);
			PkthlnClAct_SetAnm(	ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_obj_eff02_NANR,
							RES_CODE_BOOST	);
			//順位
			PkthlnClAct_SetChar( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_font_NCGR,
							RES_CODE_RANK, NNS_G2D_VRAM_TYPE_2DMAIN);
			PkthlnClAct_SetPaltt( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_font_NCLR,
							RES_CODE_RANK, NNS_G2D_VRAM_TYPE_2DMAIN, RANK_PALETTE_NUM	);
			PkthlnClAct_SetCell( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_font_NCER,
							RES_CODE_RANK	);
			PkthlnClAct_SetAnm(	ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_font_NANR,
							RES_CODE_RANK	);
			//時計・土煙
			PkthlnClAct_SetChar( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_timer_NCGR,
							RES_CODE_BWATCH, NNS_G2D_VRAM_TYPE_2DMAIN);
			PkthlnClAct_SetPaltt( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_timer_NCLR,
							RES_CODE_BWATCH, NNS_G2D_VRAM_TYPE_2DMAIN, WATCH_PALETTE_NUM	);
			PkthlnClAct_SetCell( ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_timer_NCER,
							RES_CODE_BWATCH	);
			PkthlnClAct_SetAnm(	ptr->ActCntPtr,
							ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_timer_NANR,
							RES_CODE_BWATCH	);

			PkthlnClAct_Trans(ptr->ActCntPtr);

			//共通リソース
			ptr->CmnResCntPtr = CmnRes_Init( ptr->HeapID, CMN_RES_ALL_BIT|CMN_RES_PEN_M_BIT|CMN_RES_F2X2_BIT,
											 NNS_G2D_VRAM_TYPE_2DMAIN );

			//ポケモンアクター
			ptr->PokeActCntPtr = PokeAct_Init( ptr->HeapID, HURDLE_EVENT_POKE_NUM, PRI_POKE,
									  ptr->CmnResCntPtr, PkthlnClAct_GetClActSetAdr(ptr->ActCntPtr) );

			//次のシーケンスへ
			PTFrame_IncSubSeq(work);
			break;
		case 2:
			//障害物+壊れＯＢＪ
			for(i=0;i<OBST_MAX;i++){
				CLACT_WORK_PTR act_ptr;
				act_ptr = PkthlnClAct_SetActor(ptr->ActCntPtr, MAIN_OBJ_BG_PRI,
						NNS_G2D_VRAM_TYPE_MAX, RES_CODE_OBST, ACT_CODE_OBST);
				//プライオリティセット
				CLACT_DrawPriorityChg( act_ptr, PRI_OBST );
				act_ptr = PkthlnClAct_SetActor(ptr->ActCntPtr, MAIN_OBJ_BG_PRI,
						NNS_G2D_VRAM_TYPE_2DMAIN, RES_CODE_OBST_BREAK, ACT_CODE_OBST_BREAK);
				//プライオリティセット
				CLACT_DrawPriorityChg( act_ptr, PRI_OBST );
			}
			//ジャンプエフェクト、順位、ブースト
			for(i=0;i<HURDLE_EVENT_POKE_NUM;i++){
				//ジャンプエフェクト
				PkthlnClAct_SetActor(ptr->ActCntPtr, MAIN_OBJ_BG_PRI,
						NNS_G2D_VRAM_TYPE_2DMAIN, RES_CODE_BJUMP, ACT_CODE_SHIFT);
				//順位
				PkthlnClAct_SetActor(ptr->ActCntPtr, MAIN_OBJ_BG_PRI,
						NNS_G2D_VRAM_TYPE_2DMAIN, RES_CODE_RANK, ACT_CODE_RANK);
				//ブースト
				PkthlnClAct_SetActor(ptr->ActCntPtr, MAIN_OBJ_BG_PRI,
						NNS_G2D_VRAM_TYPE_2DMAIN, RES_CODE_BOOST, ACT_CODE_BOOST);
			}
			//時計
			{
				VecFx32 vec;
				ptr->Timer.Watch = PkthlnClAct_SetGetActor(	ptr->ActCntPtr, MAIN_OBJ_BG_PRI,
															NNS_G2D_VRAM_TYPE_2DMAIN,
															RES_CODE_BWATCH, ACT_CODE_BWATCH);
				PkthlnClAct_ChgAnm(ptr->Timer.Watch, 0);
				vec.z = 0;
				vec.x = WATCH_X * FX32_ONE;
				vec.y = (MS_BG_OFS+WATCH_Y) * FX32_ONE;
				PkthlnClAct_SetPos(ptr->Timer.Watch, &vec);
				PkthlnClAct_SetActive(ptr->Timer.Watch, 1, 1);
				//プライオリティセット
				PkthlnClAct_SetPriority(ptr->Timer.Watch, PRI_WATCH);
			}
			//タイム
			{
				//共有リソースからアクター取得
				for(i=0;i<TIMER_ACT_NUM;i++){
					VecFx32 vec;
					ptr->Timer.Number[i] = CmnRes_CreateF2X2Act( ptr->CmnResCntPtr,
																 PkthlnClAct_GetClActSetAdr(ptr->ActCntPtr),
																 0,
																 ptr->HeapID );
					CLACT_SetDrawFlag(ptr->Timer.Number[i], 1);	//表示
					vec.x = TimerActPosX[i] * FX32_ONE;
					vec.y = (MS_BG_OFS + TIMER_ACT_POS_Y) * FX32_ONE;
					vec.z = 0;
					//タイマーアクターの座標セット
					CLACT_SetMatrix(ptr->Timer.Number[i], &vec);
					CLACT_AnmChg(ptr->Timer.Number[i], DefaultTimerActAnm[i]);
				}
			}

			//土煙
			H_SMOG_GENE_Setup(ptr->SmogGenePtr, ptr->ActCntPtr, MAIN_OBJ_BG_PRI);
		}

		//ポケモンアイコン
		{
			int i,j;
			int idx;
			ICON_INFO icon_info[HURDLE_EVENT_POKE_NUM*4];
			POKETHLON_ENTRY_DATA *entry;

			ptr->HpiCntPtr = HurdlePokeIcon_Alloc(ptr->HeapID);

			idx = 0;
			for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
				entry = PTFrame_GetEntryDataPtrByID(work, i);//i番目エントリデータ取得
				for(j=0;j<HURDLE_EVENT_POKE_NUM;j++){
					icon_info[idx].MonsNo = entry[j].MonsNo;
					icon_info[idx].Form = entry[j].Form;
					idx++;
				}
			}

			HurdlePokeIcon_Setup(ptr->HpiCntPtr, icon_info);

			//はじめは非表示
			HurdlePokeIcon_SetAllVanish(ptr->HpiCntPtr, 0);
		}

		{
			int i;
			MONS_INFO info[HURDLE_EVENT_POKE_NUM];
			PCLACT_SET_PARAM param;
			for(i=0;i<HURDLE_EVENT_POKE_NUM;i++){
				PTFrame_SetMonsInfo(work, PTFrameGetCurrentID(work), i, &info[i]);
				param.ShadowPos[i] =
					PTFrame_GetPokeShdwPosType(PTFrame_GetPkthlnParam(work, PTFrameGetCurrentID(work), i));
			}
			param.Quick = 0;
			param.BGPriority = MAIN_OBJ_BG_PRI;
			param.Trans = 0;
			param.ResVramType = NNS_G2D_VRAM_TYPE_2DMAIN;
			param.DrawArea = NNS_G2D_VRAM_TYPE_2DMAIN;

			PokeAct_SetPokeActor(	ptr->PokeActCntPtr, HURDLE_EVENT_POKE_NUM,
									info, &param,
									PCLACT_TCB_PRIORITY,
									0 );
		}
		//次のシーケンスへ
		PTFrame_IncSubSeq(work);
		break;
	case 3:
		if ( PokeAct_CheckActSetTask(ptr->PokeActCntPtr) ){

			PTFrame_SetDefaultVBlankFunc(ptr->bgl);	// VBlankセット

			//キャラセット
			SetBGChar(ptr->bgl, ptr->HeapID);
			//次のシーケンスへ
			PTFrame_IncSubSeq(work);
		}
		break;
	case 4:
		//BGロード
		LoadBG(ptr->bgl, ptr->HeapID);
		//BGオフセット
		G2_SetBG0Offset(0, BG_START_OFS + MS_BG_OFS);
		G2_SetBG1Offset(0, BG_START_OFS + MS_BG_OFS);
		G2_SetBG2Offset(0, BG_START_OFS + MS_BG_OFS);
		G2S_SetBG0Offset(0, BG_START_OFS);
		G2S_SetBG1Offset(0, BG_START_OFS);
		G2S_SetBG2Offset(0, BG_START_OFS);

		//1キャラ目をＮＵＬＬデータでフィルする
		///GF_BGL_CharFill(ptr->bgl, GF_BGL_FRAME0_S, 0, 1 ,0);
		//次のシーケンスへ
		PTFrame_IncSubSeq(work);
		break;
	case 5:
		{
			int i;
			//ＯＢＪの表示
			GF_Disp_GX_VisibleControl( GX_PLANEMASK_OBJ, VISIBLE_ON );		// MAIN DISP OBJ ON
			GF_Disp_GXS_VisibleControl( GX_PLANEMASK_OBJ, VISIBLE_ON );		// SUB DISP OBJ ON
			//描画を許可
			PTFrame_SetDraw(work, TRUE);
			//ポケセルアクター可視化
			for (i=0;i<HURDLE_EVENT_POKE_NUM;i++){
				POKE_ACT_PTR poke_ptr = PokeAct_GetPokeActPtr(ptr->PokeActCntPtr, i);
				PokeAct_DispCnt(poke_ptr, 1);	//表示
			}

			//次のシーケンスへ
			PTFrame_IncSubSeq(work);
		}
		break;

	case 6:
		if ( PTFrameGetCurrentID(work) == COMM_PARENT_ID ){
			//障害物データ作成
			H_OBST_GENE_MakeGenerateData(ptr->ObstGenePtr);
		}
		//次のシーケンスへ
		PTFrame_IncSubSeq(work);
		break;
	case 7:
		//ジェネレータセットアップ
		H_OBST_GENE_SetUp(ptr->ObstGenePtr, ptr->ActCntPtr);
		//カウントダウンアクター
		{
			CLACT_WORK_PTR	*act_adr;
			act_adr = PTFrame_SetCountDown( work, MS_BG_OFS, ptr->CmnResCntPtr, ptr->ActCntPtr );
			//プライオリティセット
			CLACT_DrawPriorityChg( *act_adr, PRI_COUNT );
		}
		//レーンセットアップ
		{
			int x_array[HURDLE_EVENT_POKE_NUM] = {
				RANE1_POKE_X,RANE2_POKE_X,RANE3_POKE_X
			};
			int i;
			PEN_POS pen_pos[ENTRY_MAX];
			EVT_HIT_DATA hit_data;
			HURDLE_PARAM data;
			ArchiveDataLoad(hit_data.Data, ARC_PKTHEVT_PARAM, NARC_pkthln_evt_info_dash_hit_bin);
			ArchiveDataLoad(&data, ARC_PKTHEVT_PARAM, NARC_pkthln_evt_info_dash_bin);
#ifdef PM_DEBUG
			{
				int m;
				for(m=0;m<5;m++){
					OS_Printf("hurdle_prm:%d,%d,%d,%d\n",
							data.UpDown[m], data.Fly[m], data.Accele[m], data.Speed[m]);
				}
			}
#endif


			for(i=0;i<HURDLE_EVENT_POKE_NUM;i++){
				SetUpLane(work, &data, &hit_data, ptr->ObstGenePtr, ptr->ActCntPtr, ptr->PokeActCntPtr, i, &ptr->Lane[i]);
				pen_pos[i].X = x_array[i];
				pen_pos[i].Y = MS_BG_OFS+RANE_POKE_Y;
			}

			//ペン表示
			PTFrame_SetPen( work, 0, ptr->CmnResCntPtr, ptr->ActCntPtr,
						    NNS_G2D_VRAM_TYPE_2DMAIN, ENTRY_MAX,  pen_pos);

			//親の場合はNPCデータをセットアップ
			if (PTFrameGetCurrentID(work) == COMM_PARENT_ID){
				MakeNPCCoreData(work, &data);
			}
		}


		{
			u8 i;
			COMM_EVENT_COMMON_DATA *cmm_data;
			HURDLE_PARENT_DATA *s_parent;
			HURDLE_PARENT_DATA *r_parent;
			cmm_data = PTFrame_GetEvtComCmnData(work);
			r_parent = PKTHLN_CommPack_GetData(&cmm_data->ReciveShareData);
			//データ格納
			for(i=0;i<6;i++){
				r_parent->Rank[i] = 1+(1<<4);
			}
			//親のとき、初回送信データを作成
			if (PTFrameGetCurrentID(work) == COMM_PARENT_ID){
				s_parent = PKTHLN_CommPack_GetData(&cmm_data->SendShareData);
				//データ格納
				for(i=0;i<6;i++){
					s_parent->Rank[i] = 1+(1<<4);
				}
			}
		}

		//通信アイコン
		WirelessIconEasyPokethlon( NNS_G2D_VRAM_TYPE_2DMAIN );

		//フェードイン
		WIPE_SYS_Start(	WIPE_PATTERN_FSAM, WIPE_TYPE_SHUTTERIN_DOWN,
					WIPE_TYPE_SHUTTERIN_DOWN, WIPE_FADE_BLACK,
					WIPE_DEF_DIV, WIPE_DEF_SYNC, ptr->HeapID );
		//次のシーケンスへ
		PTFrame_IncSubSeq(work);
		break;
	case 8:
		//フェードイン待ち
		if( WIPE_SYS_EndCheck() ){
			//初期化終了
			return PTH_RC_END;
		}
		break;
	}
	return PTH_RC_LOOP;
}

//--------------------------------------------------------------------------------------------
/**
 * 描画関数
 *
 * @param	work		ポケスロンワークポインタ
 * @param	*pParam		パラメータ
 *
 * @return	TRUE
 */
//--------------------------------------------------------------------------------------------
BOOL PE_HURDLE_DrawFunc(PKTHLN_PTR work, void *pParam)
{
	PKTHLN_HURDLE_PTR ptr = PTFrame_GetEventWorkPtr(work);
	//描画
///	PCLACT_Draw(ptr->PclActCntPtr);
	//ポケモンアイコン
	HurdlePokeIcon_Draw(ptr->HpiCntPtr);
	//
	PkthlnClAct_Draw(ptr->ActCntPtr);
	return TRUE;
}

//--------------------------------------------------------------------------------------------
/**
 * 競技結果計算関数
 *
 * @param	work		ポケスロンワークポインタ
 * @param	*pParam		パラメータ
 *
 * @return	TRUE
 */
//--------------------------------------------------------------------------------------------
BOOL PE_HURDLE_ResultFunc(PKTHLN_PTR work, void *pParam)
{
	int i,j;
	RSLT_PTR result_ptr;
	PKTHLN_HURDLE_PTR ptr = PTFrame_GetEventWorkPtr(work);

	OS_Printf("競技結果データ作成\n");

	result_ptr = PTFrame_GetResultPtr(work);
	RSLT_Setup( result_ptr );

	for( i=0;i<ENTRY_MEMBER_NUM_MAX;i++ ){
		int rec;
		int integer,decimal;

		rec = PTFrame_GetEvtResult(work, i);

		integer = rec/30;
		decimal = ((rec%30) * 10) /30;
		RSLT_SetResult2( work, result_ptr, i, rec,
						integer, decimal, 0, 1, 3, 1,
						msg_pkthln_rs_K1 );
	}

	//ソート
	RSLT_Sort(result_ptr, SORT_REC_SMALL);
	//得点セット
	PTC_CalcPoint(result_ptr, PKTHLN_EVT_DASH);

	//総得点に加算
	RSLT_AddTotalScore(result_ptr);

	//競技得点セット
	RSLT_SetEvtScore(result_ptr, PKTHLN_EVT_DASH);

	return TRUE;
}

//--------------------------------------------------------------------------------------------
/**
 * 終了関数
 *
 * @param	work		ポケスロンワークポインタ
 * @param	*pParam		パラメータ
 *
 * @return	TRUE
 */
//--------------------------------------------------------------------------------------------
BOOL PE_HURDLE_EndFunc(PKTHLN_PTR work, void *pParam)
{
	int i;
	PKTHLN_HURDLE_PTR ptr = PTFrame_GetEventWorkPtr(work);

	// 通信アイコン撤去
	WirelessIconEasyEnd();

	//38バイト制限無効
	PKTHLN_CommPack_SetSizeBind( PTFrame_GetCommPackPtr(work), 0 );

	//ポケモンアイコン
	HurdlePokeIcon_Free(ptr->HpiCntPtr);

	//共有データクリア
	PTFrame_ClearEvtShareDataPtr(work);

	//ジェネレータ解放
	H_SMOG_GENE_End(ptr->SmogGenePtr);
	H_OBST_GENE_Free(ptr->ObstGenePtr);

	//BG削除
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME0_M );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME1_M );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME2_M );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME3_M );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME0_S );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME1_S );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME2_S );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME3_S );

	//BMP
	GF_BGL_BmpWinDel( &ptr->Win );

	//BGL解放
	sys_FreeMemoryEz(ptr->bgl);

	//ポケアクターコントローラ解放
	PokeAct_Free(ptr->PokeActCntPtr);
	//共通リソースコントローラ解放
	CmnRes_Free(ptr->CmnResCntPtr);

	//アクター解放
	PkthlnClAct_Free(ptr->ActCntPtr);

	PKTHLN_OBJ_COMMON_DeleteCharPlttManager();

	//タッチフォントアンロード
	FontProc_UnloadFont(FONT_TOUCH);

	sys_VBlankFuncChange( NULL, NULL );	// VBlankセット
	sys_HBlankIntrSet( NULL,NULL );		// HBlankセット

	//イベントワーク解放
	PTFrame_FreeEventWork(work);

	// 上下画面を元に戻しておく
	sys.disp3DSW = DISP_3D_TO_MAIN;
	GF_Disp_DispSelect();

	//ヒープ解放
	sys_DeleteHeap( HEAPID_PT_DASH );

	return TRUE;
}

//--------------------------------------------------------------------------------------------
/**
 * VRAM設定		ポケスロンでは、ポケモン表示だけで0x30000必要となる。
 * VRAM_AB(0x40000)でないとはいらん
 *
 * @param	none
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetVramBank(void)
{
	GF_BGL_DISPVRAM tbl = {
		GX_VRAM_BG_64_E,				// メイン2DエンジンのBG
		GX_VRAM_BGEXTPLTT_NONE,			// メイン2DエンジンのBG拡張パレットM
		GX_VRAM_SUB_BG_128_C,			// サブ2DエンジンのBG
		GX_VRAM_SUB_BGEXTPLTT_NONE,		// サブ2DエンジンのBG拡張パレット

		GX_VRAM_OBJ_256_AB,				// メイン2DエンジンのOBJ
		GX_VRAM_OBJEXTPLTT_NONE,		// メイン2DエンジンのOBJ拡張パレット

		GX_VRAM_SUB_OBJ_16_I,			// サブ2DエンジンのOBJ
		GX_VRAM_SUB_OBJEXTPLTT_NONE,	// サブ2DエンジンのOBJ拡張パレット

		GX_VRAM_TEX_NONE,				// テクスチャイメージスロット
		GX_VRAM_TEXPLTT_NONE			// テクスチャパレットスロット
	};
	GF_Disp_SetBank( &tbl );
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	BG初期化
 * @param	ini				BGL
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void InitBG(GF_BGL_INI * ini)
{
  {	/* BG SYSTEM */
    GF_BGL_SYS_HEADER BGsys_data = {
      GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BGMODE_0, GX_BG0_AS_2D,
    };
    GF_BGL_InitBG( &BGsys_data );
  }

  //メイン

  {	/* MAIN DISP BG0 */
    GF_BGL_BGCNT_HEADER MBg0_Data = {
      0, 0, 0x1000, 0,
      GF_BGL_SCRSIZ_256x512, GX_BG_COLORMODE_16,
      GX_BG_SCRBASE_0xd000, GX_BG_CHARBASE_0x00000,
      GX_BG_EXTPLTT_01, 1, 0, 0, FALSE
    };
    GF_BGL_BGControlSet( ini, GF_BGL_FRAME0_M, &MBg0_Data, GF_BGL_MODE_TEXT );
    GF_BGL_ScrClear( ini, GF_BGL_FRAME0_M );
  }

  {	/* MAIN DISP BG1 */
    GF_BGL_BGCNT_HEADER MBg1_Data = {
      0, 0, 0x1000, 0,
      GF_BGL_SCRSIZ_256x512, GX_BG_COLORMODE_16,
      GX_BG_SCRBASE_0xe000, GX_BG_CHARBASE_0x00000,
      GX_BG_EXTPLTT_01, 2, 0, 0, FALSE
    };
    GF_BGL_BGControlSet( ini, GF_BGL_FRAME1_M, &MBg1_Data, GF_BGL_MODE_TEXT );
    GF_BGL_ScrClear( ini, GF_BGL_FRAME1_M );
  }

  {	/* MAIN DISP BG2 */
    GF_BGL_BGCNT_HEADER MBg2_Data = {
      0, 0, 0x1000, 0,
      GF_BGL_SCRSIZ_256x512, GX_BG_COLORMODE_16,
      GX_BG_SCRBASE_0xf000, GX_BG_CHARBASE_0x00000,
      GX_BG_EXTPLTT_01, 3, 0, 0, FALSE
    };
    GF_BGL_BGControlSet( ini, GF_BGL_FRAME2_M, &MBg2_Data, GF_BGL_MODE_TEXT );
    GF_BGL_ScrClear( ini, GF_BGL_FRAME2_M );
  }

  {	/* MAIN DISP BG3 */
    	GF_BGL_BGCNT_HEADER MBg3_Data = {
	      0, 0, 0x800, 0,
    	  GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
		  GX_BG_SCRBASE_0xc800, GX_BG_CHARBASE_0x04000,
		  GX_BG_EXTPLTT_01, 0, 0, 0, FALSE
   	 };
   	GF_BGL_BGControlSet( ini, GF_BGL_FRAME3_M, &MBg3_Data, GF_BGL_MODE_TEXT );
   	GF_BGL_ScrClear( ini, GF_BGL_FRAME3_M );
  }

  //サブ

  {	/* SUB DISP BG0 */
    GF_BGL_BGCNT_HEADER SBg0_Data = {
      0, 0, 0x1000, 0,
      GF_BGL_SCRSIZ_256x512, GX_BG_COLORMODE_16,
      GX_BG_SCRBASE_0xd000, GX_BG_CHARBASE_0x00000,
      GX_BG_EXTPLTT_01, 1, 0, 0, FALSE
    };
    GF_BGL_BGControlSet( ini, GF_BGL_FRAME0_S, &SBg0_Data, GF_BGL_MODE_TEXT );
    GF_BGL_ScrClear( ini, GF_BGL_FRAME0_S );
  }

  {	/* SUB DISP BG1 */
    GF_BGL_BGCNT_HEADER SBg1_Data = {
      0, 0, 0x1000, 0,
      GF_BGL_SCRSIZ_256x512, GX_BG_COLORMODE_16,
      GX_BG_SCRBASE_0xe000, GX_BG_CHARBASE_0x00000,
      GX_BG_EXTPLTT_01, 2, 0, 0, FALSE
    };
    GF_BGL_BGControlSet( ini, GF_BGL_FRAME1_S, &SBg1_Data, GF_BGL_MODE_TEXT );
    GF_BGL_ScrClear( ini, GF_BGL_FRAME1_S );
  }

  {	/* SUB DISP BG2 */
    GF_BGL_BGCNT_HEADER SBg2_Data = {
      0, 0, 0x1000, 0,
      GF_BGL_SCRSIZ_256x512, GX_BG_COLORMODE_16,
      GX_BG_SCRBASE_0xf000, GX_BG_CHARBASE_0x00000,
      GX_BG_EXTPLTT_01, 3, 0, 0, FALSE
    };
    GF_BGL_BGControlSet( ini, GF_BGL_FRAME2_S, &SBg2_Data, GF_BGL_MODE_TEXT );
    GF_BGL_ScrClear( ini, GF_BGL_FRAME2_S );
  }

  {	/* SUB DISP BG3 */
    GF_BGL_BGCNT_HEADER SBg3_Data = {
      0, 0, 0x800, 0,
      GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
      GX_BG_SCRBASE_0xc800, GX_BG_CHARBASE_0x00000,
      GX_BG_EXTPLTT_01, 0, 0, 0, FALSE
    };
    GF_BGL_BGControlSet( ini, GF_BGL_FRAME3_S, &SBg3_Data, GF_BGL_MODE_TEXT );
    GF_BGL_ScrClear( ini, GF_BGL_FRAME3_S );
  }
  //レコードＢＧ非表示
  GF_Disp_GX_VisibleControl( GX_PLANEMASK_BG3, VISIBLE_OFF );
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	BGキャラセット
 * @param	ini				BGL
 * @param	inHeapID		ヒープID
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetBGChar(GF_BGL_INI * ini, const int inHeapID)
{
	//キャラ(フレーム0〜2まで共通)
	ArcUtil_BgCharSet(ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_lane_ncgr,
						ini, GF_BGL_FRAME0_M, 0, 0, FALSE, inHeapID);
	//キャラ(フレーム0〜2まで共通)
	ArcUtil_BgCharSet(ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_lane_ncgr,
						ini, GF_BGL_FRAME0_S, 0, 0, FALSE, inHeapID);
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	BGロード
 * @param	ini				BGL
 * @param	inHeapID		ヒープID
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void LoadBG(GF_BGL_INI * ini, const int inHeapID)
{
	//スクリーン
	ArcUtil_ScrnSet(ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_lane_left_nscr,
						ini, GF_BGL_FRAME0_M, 0, 0, FALSE, inHeapID);
	ArcUtil_ScrnSet(ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_lane_center_nscr,
						ini, GF_BGL_FRAME1_M, 0, 0, FALSE, inHeapID);
	ArcUtil_ScrnSet(ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_lane_right_nscr,
						ini, GF_BGL_FRAME2_M, 0, 0, FALSE, inHeapID);
	//スクリーン
	ArcUtil_ScrnSet(ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_lane_left_nscr,
						ini, GF_BGL_FRAME0_S, 0, 0, FALSE, inHeapID);
	ArcUtil_ScrnSet(ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_lane_center_nscr,
						ini, GF_BGL_FRAME1_S, 0, 0, FALSE, inHeapID);
	ArcUtil_ScrnSet(ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_lane_right_nscr,
						ini, GF_BGL_FRAME2_S, 0, 0, FALSE, inHeapID);
	ArcUtil_ScrnSet(ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_lane_sub_nscr,
						ini, GF_BGL_FRAME3_S, 0, 0, FALSE, inHeapID);

	//パレット
	ArcUtil_PalSet( ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_lane_nclr,
						PALTYPE_MAIN_BG, 0, 32, inHeapID );
	//パレット
	ArcUtil_PalSet( ARC_PKTHEV_DASH, NARC_pkthev_dash_dash_lane_nclr,
						PALTYPE_SUB_BG, 0, 32, inHeapID );
}

///////////////////////////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------------------
/**
 * @brief	レーンごとの処理
 *
 * @param	work			ワーク
 * @param	inData			ハードルパラム
 * @param	inHitData		ヒットデータ
 * @param	pGenePtr		ジェネレータポインタ
 * @param	pActCntPtr		アクタ管理ポインタ
 * @param	pPokeActCntPtr	ポケモンアクタ管理ポインタ
 * @param	inLaneIdx		レーンインデックス
 * @param	outLane			レーンデータポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetUpLane(	PKTHLN_PTR work, const HURDLE_PARAM *inData, EVT_HIT_DATA *inHitData,
						H_OBST_GENERATE_PTR pGenePtr, PKTHLN_CLACT_CNT_PTR pActCntPtr, POKE_ACT_CNT_PTR pPokeActCntPtr,
						const u8 inLaneIdx, HURDLE_LANE *outLane)
{
	POKE_ACT_PTR poke_ptr;
	PCLACT_PTR	pclact_ptr;

	outLane->RunLength = 0;		//走行距離
	outLane->Time = 0;		//時間
	outLane->S_BGOffset = BG_START_OFS;
	outLane->M_BGOffset = BG_START_OFS + MS_BG_OFS;
	outLane->LaneNo = inLaneIdx;
	outLane->LocalRank = 1;
	outLane->RankScale = 1.0;

	outLane->Finished = FINISH_NONE;		//ゴールしたかフラグ
	outLane->ObstArray = H_OBST_GENE_GetObstArray(pGenePtr, inLaneIdx);

	switch(inLaneIdx){
	case 0:
		outLane->MainFrameNo = GF_BGL_FRAME0_M;
		outLane->SubFrameNo = GF_BGL_FRAME0_S;
		break;
	case 1:
		outLane->MainFrameNo = GF_BGL_FRAME1_M;
		outLane->SubFrameNo = GF_BGL_FRAME1_S;
		break;
	case 2:
		outLane->MainFrameNo = GF_BGL_FRAME2_M;
		outLane->SubFrameNo = GF_BGL_FRAME2_S;
		break;
	}

	{
		int poke_idx;
		int x;
		const MONS_INFO *info;
		VecFx32 aff_vec;

		switch(inLaneIdx){
		case 0:
			poke_idx = 0;
			//座標セット
			x = RANE1_POKE_X;
			break;
		case 1:
			poke_idx = 1;
			x = RANE2_POKE_X;
			break;
		case 2:
			poke_idx = 2;
			x = RANE3_POKE_X;
			break;
		default:
			GF_ASSERT(0);
			return ;
		}

		poke_ptr = PokeAct_GetPokeActPtr(pPokeActCntPtr, poke_idx);
		pclact_ptr = PokeAct_GetPclActPtr(poke_ptr);

		outLane->DashPoke.PokeActPtr = poke_ptr;

		info = PCLACT_GetMonsInfo(pclact_ptr);



		//ポケモンごとのパラメータ設定
		{
			int i;
			u8 updown;
			u8 fly;
			const POKE_SPEC *spec;
			spec = PTFrame_GetPokeSpec(work, PTFrameGetCurrentID(work), inLaneIdx);

			outLane->DashPoke.PokeParam.UpDownFrame = inData->UpDown[spec->Jump];
			outLane->DashPoke.PokeParam.FlyFrame = inData->Fly[spec->Jump];
			outLane->DashPoke.PokeParam.JumpLv = spec->Jump;
			//あたり判定データセット
			{
				HIT_TYPE hit_type;
				int net_id;
				net_id = PTFrameGetCurrentID(work);
				hit_type = PTFrame_GetPokeHitType(PTFrame_GetPkthlnParam(work, net_id, inLaneIdx));
				PokeAct_SetHitData(poke_ptr, inHitData->Data[hit_type-1].Ofs, inHitData->Data[hit_type-1].Range);
			}

			//タッチ半径セット
			PokeAct_SetTouchRange(poke_ptr, PTFrame_GetPokeTouchRange());
			//速度関連
			outLane->DashPoke.PokeParam.BaseSpeed = (float)inData->Speed[spec->Speed]/10;			//値を1/10にして使用
			outLane->DashPoke.PokeParam.AcceleSpeed = (float)inData->Accele[spec->Technique]/100;	//値を1/100にして使用

			OS_Printf("hurdel_prm:%d,%d,%f,%f\n",
					outLane->DashPoke.PokeParam.UpDownFrame,
					outLane->DashPoke.PokeParam.FlyFrame,
					outLane->DashPoke.PokeParam.BaseSpeed,
					outLane->DashPoke.PokeParam.AcceleSpeed);
		}

		if (info->CellType){
			aff_vec.x = (BIG_POKE_SIZE/2)*FX32_ONE;
			aff_vec.y = (BIG_POKE_SIZE/2)*FX32_ONE;
		}else{
			aff_vec.x = (SMALL_POKE_SIZE/2)*FX32_ONE;
			aff_vec.y = (SMALL_POKE_SIZE/2)*FX32_ONE;
		}

		//ポケモン位置セット
		outLane->DashPoke.RunPos = RANE_POKE_Y;
		//アクター位置セット
///dd		PokeAct_SetPos(outLane->DashPoke.PokeActPtr, x+ofs_x, MS_BG_OFS+outLane->DashPoke.RunPos-space, TRUE);
		PokeAct_SetPosShadow(poke_ptr, x, MS_BG_OFS+outLane->DashPoke.RunPos);

		PokeAct_SetDir(poke_ptr, POKE_DIR_UP);

		//ポケモンプライオリティセット
		PokeAct_SetPriority(poke_ptr, PRI_POKE);
		//アフィン
		PokeAct_SetAffine(poke_ptr, CLACT_AFFINE_DOUBLE);
		//アフィン座標セット
		PokeAct_SetAffineVec(poke_ptr, &aff_vec);
		//ジャンプエフェクトセット
		{
			VecFx32 vec;
			CLACT_WORK_PTR act_ptr;
			outLane->DashPoke.ShiftPtr =
				PkthlnClAct_GetActPtr(pActCntPtr, RES_CODE_BJUMP, ACT_CODE_SHIFT);
			act_ptr = PkthlnClAct_GetClActWorkPtr( outLane->DashPoke.ShiftPtr );
///			CLACT_AnmChg( act_ptr, 2 );	//初期はシフトアップということにしておく
			outLane->DashPoke.ShiftEffPos = MS_BG_OFS+outLane->DashPoke.RunPos  + /*SHIFT_EFF_OFS*/16;
			vec.z = 0;
			vec.x = x * FX32_ONE;
			vec.y = outLane->DashPoke.ShiftEffPos * FX32_ONE;
			CLACT_SetMatrix( act_ptr, &vec );
			PkthlnClAct_SetActive(outLane->DashPoke.ShiftPtr, 1, 0);	//不可視でセット
			//プライオリティセット
			CLACT_DrawPriorityChg( act_ptr, PRI_SHIFT );
		}
		//順位ＯＢＪセット
		{
			VecFx32 vec;
			CLACT_WORK_PTR act_ptr;
			outLane->DashPoke.RankPtr =
				PkthlnClAct_GetActPtr(pActCntPtr, RES_CODE_RANK, ACT_CODE_RANK);
			act_ptr = PkthlnClAct_GetClActWorkPtr( outLane->DashPoke.RankPtr );
			CLACT_AnmChg( act_ptr, 0 );	//初期は1位ということにしておく
			vec.z = 0;
			vec.x = x * FX32_ONE;
			vec.y = RANK_DISP_POS * FX32_ONE;
			CLACT_SetMatrix( act_ptr, &vec );
			//プライオリティセット
			CLACT_DrawPriorityChg( act_ptr, PRI_RANK );
			//アフィン
			CLACT_SetAffineParam( act_ptr, CLACT_AFFINE_DOUBLE );
		}
		//ブースト
		{
			VecFx32 vec;
			CLACT_WORK_PTR act_ptr;
			outLane->DashPoke.BoostPtr =
				PkthlnClAct_GetActPtr(pActCntPtr, RES_CODE_BOOST, ACT_CODE_BOOST);
			act_ptr = PkthlnClAct_GetClActWorkPtr( outLane->DashPoke.BoostPtr );
			CLACT_AnmChg( act_ptr, 0 );
			vec.z = 0;
			vec.x = x * FX32_ONE;
			vec.y = (MS_BG_OFS+RANE_POKE_Y) * FX32_ONE;
			CLACT_SetMatrix( act_ptr, &vec );
			PkthlnClAct_SetActive(outLane->DashPoke.BoostPtr, 1, 1);
			//プライオリティセット
			CLACT_DrawPriorityChg( act_ptr, PRI_BOOST );
		}
	}

	//スピード設定
	outLane->SpeedF = START_SPEED;
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	障害物OBJポインタ取得
 * @param	inLane	レーンのポインタ
 * @param	inIdx	インデックス
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static H_OBST_PTR LANE_GetObstPtr(HURDLE_LANE *inLane, const int inIdx)
{
	return H_OBST_GetObstPtr(inLane->ObstArray, inIdx);
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	レーン処理メイン
 *
 * @param	work		ポケスロンワーク
 * @param	ptr			競技ワーク
 * @param	inLane		レーンポインタ
 * @param	inTouchReq	タッチリクエスト
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void LaneMain(PKTHLN_PTR work, PKTHLN_HURDLE_PTR ptr, HURDLE_LANE *inLane, const TOUCH_REQ *inTouchReq)
{
	int speed;
	float temp;

	//加速処理
	if ( (inLane->Finished != FINISH_GOAL)&&
		( inLane->DashPoke.State != D_POKE_ST_PENALTY_DOWN )&&
		 (inLane->Boost == 0)&&
		 (inLane->SpeedF < inLane->DashPoke.PokeParam.BaseSpeed) ){
		inLane->SpeedF += inLane->DashPoke.PokeParam.AcceleSpeed;
		if (inLane->SpeedF > inLane->DashPoke.PokeParam.BaseSpeed){
			inLane->SpeedF = inLane->DashPoke.PokeParam.BaseSpeed;
		}
	}



	if ((inTouchReq != NULL)&&(inLane->DashPoke.State == D_POKE_ST_NONE)){
		BOOL boost_success;
		int i;
		DashPokeSetState(work, inTouchReq->Y, inLane->LaneNo, &inLane->DashPoke);
		OS_Printf("リクエストを受け付けた\n");
		boost_success = FALSE;
		//ブースト
		if (inLane->DashPoke.PokeParam.JumpLv > 0){
			for(i=0;i<OBST_NUM;i++){
				HIT_RECT rect;
				H_OBST_PTR obst;
				obst = LANE_GetObstPtr(inLane, i);
				if ( H_OBST_IsHitValid(obst) ){
					BOOL boost;
					int bst_y;
					//ヒット矩形取得
					H_OBST_GetHitRect(obst, &rect);
					bst_y = inLane->DashPoke.RunPos+MS_BG_OFS-PokeAct_GetHitRange(inLane->DashPoke.PokeActPtr);
					boost = CheckBoost(bst_y, &rect);
					if ( boost ){
						OS_Printf("ブースト成功\n");
						boost_success = TRUE;
						Boost(work, inLane);
						break;
					}
				}
			}	//end for
		}
		//ジャンプエフェクト表示
		{
			CLACT_WORK_PTR act_ptr;
			act_ptr = PkthlnClAct_GetClActWorkPtr( inLane->DashPoke.ShiftPtr );
			CLACT_SetDrawFlag(act_ptr, 1);	//表示
			if (boost_success){
				CLACT_AnmChg( act_ptr, 0 );	//ブーストジャンプ
			}else{
				CLACT_AnmChg( act_ptr, 1 );	//通常ジャンプ
			}
		}
	}else if ((inTouchReq != NULL)&&(inLane->DashPoke.State == D_POKE_ST_JUMP)&&
			(inLane->DashPoke.LST.St == LST_JUMP_DOWN)&&
			(inLane->DashPoke.PokeParam.JumpLv > 0) ){
		//2段ジャンプフラグオン(予約)
		inLane->DashPoke.DoubleJump = 1;
		inLane->DashPoke.DblJumpTouchNum++;
	}//end if(inTouchReq != NULL)

	temp = inLane->SpeedF+inLane->RestSpeed;
	speed = temp;
	inLane->RestSpeed = temp - speed;

///	OS_Printf("SPEED_F:SPPED = %f:%d\n",inLane->SpeedF,speed);
///	OS_Printf("REST_SPEED = %f\n",inLane->RestSpeed);

	//走行処理加算
	inLane->RunLength += speed;

	//障害物ジェネレート判定
	GenerateObst(ptr, inLane->RunLength, inLane->LaneNo);

	//土煙ジェネレート
	GenerateSmog(ptr, inLane);

	//BGスクロール
	{
		int dif;
		int m_v_ofs;
		inLane->S_BGOffset -= speed;

		dif = 512 + inLane->S_BGOffset;
		if (dif<=0){
			inLane->S_BGOffset = dif;
		}
		inLane->M_BGOffset = MS_BG_OFS + inLane->S_BGOffset;

		dif = 512 + inLane->M_BGOffset;
		if (dif<=0){
			inLane->M_BGOffset = dif;
		}
	}

	//障害物前進処理
	{
		int i;
		for(i=0;i<OBST_NUM;i++){
			H_OBST_PTR obst;
			obst = LANE_GetObstPtr(inLane, i);
			H_OBST_Move(obst, speed);
		}
	}

	//土煙動作処理
	H_SMOG_GENE_Move(ptr->SmogGenePtr, inLane->LaneNo, speed);

	//ポケ動作
	DashPokeMove(inLane->LaneNo, &inLane->DashPoke, &inLane->SpeedF);

	//ゴールしているなら当たり判定以下の処理は、行わない
	if (inLane->Finished == FINISH_GOAL){
		//動作終了後ステート変更
		if (inLane->DashPoke.State == D_POKE_ST_NONE){
			inLane->DashPoke.State = D_POKE_ST_GOAL_MOVE;
		}else if( (inLane->DashPoke.State == D_POKE_ST_GOAL_MOVE) || (inLane->DashPoke.State == D_POKE_ST_JUMP) ){
			int y;
			y = inLane->DashPoke.RunPos;
			//走行距離がLANE_LENGTH+GOAL_FINISH_LEN以上か？
			if ( inLane->RunLength >= LANE_LENGTH+GOAL_FINISH_LEN ){
				if(y == GOAL_AFTER_POS){		//アクターが規定位置にいるならば、ステータス変更
					inLane->DashPoke.State = D_POKE_ST_FINISHED;	//動作終了
					inLane->SpeedF = 0;	//停止
					inLane->RestSpeed = 0;
				}
			}else if (inLane->RunLength >= LANE_LENGTH){
				//走行距離がLANE_LENGTH以上で、スピードを一定にする
				inLane->SpeedF = GOAL_SPEED;
				inLane->RestSpeed = 0;
				//ポケ動作元に戻す
				PokeAct_SetDir(inLane->DashPoke.PokeActPtr, POKE_DIR_UP);
				//ブースト消す
				{
					CLACT_WORK_PTR act_ptr;
					act_ptr = PkthlnClAct_GetClActWorkPtr( inLane->DashPoke.BoostPtr );
					CLACT_AnmChg( act_ptr, NONE_BOOST );
				}
			}
		}
		//スクリーン転送処理
		TransScreen(ptr->bgl, inLane);
		return ;
	}

	//当たり判定（ポケと障害物）
	{
		int i;
		u8 need_check = 1;

		//ジャンプ中
		if (inLane->DashPoke.State == D_POKE_ST_JUMP){
			need_check = 0;
		}
		//２段ジャンプ予約がある(降下中に一回だけタッチした場合、２回以上は、反則とみなし、ダブルジャンプしない)
		if ( (inLane->DashPoke.DoubleJump == 1)&&(inLane->DashPoke.DblJumpTouchNum == 1) ){
			need_check = 1;
		}

		if ( (inLane->DashPoke.DoubleJump == 1)&&(inLane->DashPoke.DblJumpTouchNum > 1) ){
			OS_Printf("タッチしすぎ\n");
		}

		if (need_check){
			//障害物座標を取得しヒッチ
			for(i=0;i<OBST_NUM;i++){
				HIT_RECT rect;
				H_OBST_PTR obst;

				obst = LANE_GetObstPtr(inLane, i);
				if ( H_OBST_IsHitValid(obst) ){
					BOOL hit;
					POKE_ACT_PTR poke_act_ptr = inLane->DashPoke.PokeActPtr;
					//ヒット矩形取得
					H_OBST_GetHitRect(obst, &rect);
					hit = CheckHit( inLane->DashPoke.RunPos+MS_BG_OFS-PokeAct_GetHitOfs(poke_act_ptr),
									PokeAct_GetHitRange(poke_act_ptr),
									&rect);
					if ( hit  ){
						H_OBST_InvalidHit(obst);

						Snd_SePlayEx( SE_HURDLE_HIT, SndPlayer[inLane->LaneNo] );		//衝突SE
						Snd_PanSetByPlayerNo( SndPlayer[inLane->LaneNo], SndPan[inLane->LaneNo] );	//パン設定

						if ( (inLane->DashPoke.DoubleJump == 1)&&(inLane->DashPoke.DblJumpTouchNum == 1) ){
							//アクションポイント加算「ジャンプ回数」
							PTFrame_AddActionPoint(	work, PTFrameGetCurrentID(work), inLane->LaneNo, ADD_TYPE_JUMP, 1 );
							//↑※２段ジャンプできるポケはジャンプできるポケ限定なのでここでのジャンプレベル判定は行わない（DoubleJump == 1を満たすのはジャンプできるポケのみ）
							//２段ジャンプ成功
							inLane->DashPoke.LST.Count = DOUBLE_JUMP_START_FRAME;
							inLane->DashPoke.LST.St = LST_JUMP_UP;	//上昇中
							OS_Printf("２段ジャンプブースト成功\n");
							Boost(work, inLane);
						}else{
///							OS_Printf("ヒットしました\n");
							inLane->SpeedF = PENALTY_SPEED;	//スピードを最低にする
							inLane->Boost = 0;		//ブースト値0
							inLane->DashPoke.State = D_POKE_ST_PENALTY_DOWN;
							//ペナルティ間パラメータセット
							inLane->DashPoke.LST.SpinCount = 0;
							inLane->DashPoke.LST.SpinDir = POKE_DIR_UP;
							inLane->DashPoke.LST.St = LST_PENALTY;		//ペナルティ中
							//ブーストダウン
							{
								CLACT_WORK_PTR act_ptr;
								act_ptr = PkthlnClAct_GetClActWorkPtr( inLane->DashPoke.BoostPtr );
								CLACT_AnmChg( act_ptr, NONE_BOOST );
							}
							//アクションポイント加算「失敗回数」
							PTFrame_AddActionPoint(	work, PTFrameGetCurrentID(work), inLane->LaneNo, ADD_TYPE_FAIL, 1 );
						}
						inLane->DashPoke.DoubleJump = 0;
						inLane->DashPoke.DblJumpTouchNum = 0;
					}
				}
			}//end for

		}	//end if (need_check)
	}

	//レーンごとのゴール判定
	if ( (inLane->Finished!=FINISH_GOAL)&&(inLane->RunLength >= LANE_LENGTH) ){
		inLane->Finished = FINISH_GOAL;	//ゴール
		//タイム記憶
		inLane->Time = ptr->GameTime;
		//ゴールＳＥ（自分）
		Snd_SePlayEx( SE_THLON_MY_GOAL, SndPlayer[inLane->LaneNo] );
		//ランキングに更新がかかるように更新カウンタをセット
		ptr->DrawRankFrame = DRAW_RANK_FRAME;
	}

	//スクリーン転送処理
	TransScreen(ptr->bgl, inLane);

}

//--------------------------------------------------------------------------------------------
/**
 * @brief	レーン処理メイン
 *
 * @param	work	ポケスロンワーク
 * @param	ptr		競技アプリポインタ
 *
 * @return	BOOL	全員ゴールでTRUE
 */
//--------------------------------------------------------------------------------------------
static BOOL LaneCntMain(PKTHLN_PTR work, PKTHLN_HURDLE_PTR ptr)
{
	BOOL rc;
	int i;
	u8 finish;
	HURDLE_LANE *lane;
	TOUCH_REQ touch_req;
	int touch_idx;

	rc = FALSE;

	//タッチリクエスト

	{
		touch_idx = -1;
		touch_req.Lane = -1;
		touch_req.Y = 0;
		if ( GF_TP_GetTrg() ){
			//アクションポイント加算「タッチ回数」
			PTFrame_AddActionPoint(	work, PTFrameGetCurrentID(work), ENTRY_MAX, ADD_TYPE_TOUCH, 1 );
			touch_idx = CheckPokeTouch(ptr, sys.tp_x, sys.tp_y);
			if (touch_idx < HURDLE_EVENT_POKE_NUM){
				touch_req.Lane = touch_idx;
			}
		}
	}

	finish = 0;
	for(i=0;i<HURDLE_EVENT_POKE_NUM;i++){
		TOUCH_REQ *req = NULL;
		lane = &ptr->Lane[i];
		if (!lane->Finished){
			if (touch_idx == i){
				req = &touch_req;
			}
		}else{
			finish++;
		}
		LaneMain(work, ptr, lane, req);
	}

	//BGオフセット
	G2_SetBG0Offset(0, ptr->Lane[0].M_BGOffset);
	G2_SetBG1Offset(0, ptr->Lane[1].M_BGOffset);
	G2_SetBG2Offset(0, ptr->Lane[2].M_BGOffset);
	G2S_SetBG0Offset(0, ptr->Lane[0].S_BGOffset);
	G2S_SetBG1Offset(0, ptr->Lane[1].S_BGOffset);
	G2S_SetBG2Offset(0, ptr->Lane[2].S_BGOffset);

	//ゴール判定
	if (finish >= HURDLE_EVENT_POKE_NUM){
		OS_Printf("１レーン タイム%d\n",ptr->Lane[0].Time);
		OS_Printf("２レーン タイム%d\n",ptr->Lane[1].Time);
		OS_Printf("３レーン タイム%d\n",ptr->Lane[2].Time);
		OS_Printf("全員ゴールしました\n");
		rc = TRUE;
	}

	return rc;
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケモンステート発行
 *
 *  @param	work			ポケスロンワーク
 *	@param	inY				Y座標
 *	@param	inIdx			レーンインデックス
 *	@param	*ioDashPoke		走行ポケモンデータポインタ
 *
 *	@return none
 */
//-----------------------------------------------------------------------------
static void DashPokeSetState(PKTHLN_PTR work, const int inY, const u8 inIdx, HURDLE_POKE *ioDashPoke)
{
	int x,y;
	//ステート発行中の場合は上書きしない
	if (ioDashPoke->State != D_POKE_ST_NONE){
		return;
	}

	//ポケモンにタッチ
	//SE(ジャンプするポケのみ)
	if ( ioDashPoke->PokeParam.JumpLv != 0 ){
		//ジャンプＳＥ
		Snd_SePlayEx( SE_THLON_JUMP, SndPlayer[inIdx] );		//ジャンプSE
		//アクションポイント加算「ジャンプ回数」
		PTFrame_AddActionPoint(	work, PTFrameGetCurrentID(work), inIdx, ADD_TYPE_JUMP, 1 );
	}else{
		//もぐるＳＥ
		Snd_SePlayEx( SE_HURDLE_MOGURU, SndPlayer[inIdx] );		//ジャンプSE
	}
	Snd_PanSetByPlayerNo( SndPlayer[inIdx], SndPan[inIdx] );	//パン設定
	//ジャンプ
	ioDashPoke->State = D_POKE_ST_JUMP;
	ioDashPoke->LST.Count = 0;
	ioDashPoke->LST.St = LST_JUMP_UP;	//上昇中
	PokeAct_GetPos(ioDashPoke->PokeActPtr, &ioDashPoke->LST.bf_jump_x, &ioDashPoke->LST.bf_jump_y );
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケモン動作関数
 *
 *  @param	inLaneIdx		レーンインデックス
 *	@param	*outDashPoke	走行ポケモンデータポインタ
 *	@param	*outSpeed		スピード
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void DashPokeMove(const u8 inLaneIdx, HURDLE_POKE *outDashPoke, float *outSpeed)
{
	switch(outDashPoke->State){
	case D_POKE_ST_JUMP:
		outDashPoke->LST.Count++;
		switch(outDashPoke->LST.St){
		case LST_JUMP_UP:
			{
				int y;
				int y_ofs;
				//座標変更
				y_ofs = HurdeJumpUp[outDashPoke->PokeParam.JumpLv][outDashPoke->LST.Count-1];
				y = outDashPoke->LST.bf_jump_y - y_ofs;

				//拡縮処理
				if (outDashPoke->PokeParam.JumpLv == 0){
					SetNonJmpPokeScale(outDashPoke, 0);
					PokeAct_SetPosPokeOnly(outDashPoke->PokeActPtr, outDashPoke->LST.bf_jump_x, y);
				}else{
					SetPokeScale(outDashPoke, y_ofs);
					PokeAct_SetPos(outDashPoke->PokeActPtr, outDashPoke->LST.bf_jump_x, y, FALSE);
				}

				if (outDashPoke->LST.Count >= outDashPoke->PokeParam.UpDownFrame){
					//ジャンプ滞空へ
					outDashPoke->LST.St = LST_JUMP_KEEP;
					outDashPoke->LST.Count = 0;

					//ジャンプ値0のポケは非表示
					if (outDashPoke->PokeParam.JumpLv == 0){
						PokeAct_PokeDispCnt(outDashPoke->PokeActPtr, 0);
					}
				}
			}
			break;
		case LST_JUMP_KEEP:
			if (outDashPoke->LST.Count >= outDashPoke->PokeParam.FlyFrame){
				//ジャンプ降下へ
				outDashPoke->LST.St = LST_JUMP_DOWN;
				outDashPoke->LST.Count = 0;
				//ジャンプ値0のポケは表示開始
				if (outDashPoke->PokeParam.JumpLv == 0){
					PokeAct_PokeDispCnt(outDashPoke->PokeActPtr, 1);
					//地面から出るＳＥ(もぐるＳＥと同じ)
					Snd_SePlayEx( SE_HURDLE_MOGURU, SndPlayer[inLaneIdx] );		//ジャンプSE
					Snd_PanSetByPlayerNo( SndPlayer[inLaneIdx], SndPan[inLaneIdx] );	//パン設定
				}
			}
			break;
		case LST_JUMP_DOWN:
			{
				int y;
				int y_ofs;
				//座標変更
				y_ofs = HurdeJumpDown[outDashPoke->PokeParam.JumpLv][outDashPoke->LST.Count-1];
				y = outDashPoke->LST.bf_jump_y - y_ofs;

				//拡縮処理
				if (outDashPoke->PokeParam.JumpLv == 0){
					SetNonJmpPokeScale(outDashPoke, 1);
					PokeAct_SetPosPokeOnly(outDashPoke->PokeActPtr, outDashPoke->LST.bf_jump_x, y);
				}else{
					SetPokeScale(outDashPoke, y_ofs);
					PokeAct_SetPos(outDashPoke->PokeActPtr, outDashPoke->LST.bf_jump_x, y, FALSE);
				}

				if (outDashPoke->LST.Count >= outDashPoke->PokeParam.UpDownFrame){
					//着地
					outDashPoke->State = D_POKE_ST_NONE;
					outDashPoke->LST.St = LST_NONE;
					outDashPoke->LST.Count = 0;
					PokeAct_SetPos( outDashPoke->PokeActPtr,
									outDashPoke->LST.bf_jump_x, outDashPoke->LST.bf_jump_y,
									FALSE);
					//SE(ジャンプするポケのみ)
					if ( outDashPoke->PokeParam.JumpLv != 0 ){
						Snd_SePlayEx( SE_HURDLE_LANDING, SndPlayer[inLaneIdx] );
						Snd_PanSetByPlayerNo( SndPlayer[inLaneIdx], SndPan[inLaneIdx] );	//パン設定
					}
					SetPokeScale(outDashPoke, 0);		//拡縮処理(スケールを１倍にする)
					//２段ジャンプフラグオフ
					outDashPoke->DoubleJump = 0;
					outDashPoke->DblJumpTouchNum = 0;
				}else if (outDashPoke->LST.Count < outDashPoke->PokeParam.UpDownFrame-DBL_JUMP_FRAME){
					//２段ジャンプフラグオフ
					outDashPoke->DoubleJump = 0;
				}
			}
			break;
		default:
			GF_ASSERT(0);
		}
		break;
	case D_POKE_ST_PENALTY_DOWN:
		{
			int x,y;
			//内部パラメータ変更ならびに、座標変更
			outDashPoke->LST.Count++;
			//スピン
			if (outDashPoke->LST.SpinCount == 0){
				switch(outDashPoke->LST.SpinDir){
				case POKE_DIR_UP:
					outDashPoke->LST.SpinDir = POKE_DIR_LEFT;
					break;
				case POKE_DIR_LEFT:
					outDashPoke->LST.SpinDir = POKE_DIR_DOWN;
					break;
				case POKE_DIR_DOWN:
					outDashPoke->LST.SpinDir = POKE_DIR_RIGHT;
					break;
				case POKE_DIR_RIGHT:
					outDashPoke->LST.SpinDir = POKE_DIR_UP;
					break;
				}
				//スピン
				PokeAct_SetDir(outDashPoke->PokeActPtr, outDashPoke->LST.SpinDir);
			}//end if
			outDashPoke->LST.SpinCount = (outDashPoke->LST.SpinCount+1)%SPIN_WAIT;

			if (outDashPoke->LST.Count>PENALTY_TIME){
				outDashPoke->LST.Count = 0;
				outDashPoke->State = D_POKE_ST_NONE;
				outDashPoke->LST.St = LST_NONE;
				PokeAct_SetDir(outDashPoke->PokeActPtr, POKE_DIR_UP);
			}
		}
		break;
	case D_POKE_ST_GOAL_MOVE:	//ゴール後調整歩き
		{
			BOOL chg;
			int add;
			int y;

			y = outDashPoke->RunPos;
			chg = FALSE;
			//ゴール後規定位置に移動
			if (GOAL_AFTER_POS > y){
				//後退
				add = GOAL_AF_SPEED;
				if (GOAL_AFTER_POS < y+add){
					add = y - GOAL_AFTER_POS;
				}
				chg = TRUE;
			}else if(GOAL_AFTER_POS < y){
				//前進
				add = -GOAL_AF_SPEED;
				if (GOAL_AFTER_POS > y+add){
					add = GOAL_AFTER_POS-y;
				}
				chg = TRUE;
			}

			if (chg){
				outDashPoke->RunPos += add;
				outDashPoke->ShiftEffPos += add;
				PokeAct_Move(outDashPoke->PokeActPtr, 0, add, POKE_DIR_UP, TRUE);
			}
		}
		break;
	case D_POKE_ST_NONE:
		//２段ジャンプフラグオフ
		outDashPoke->DoubleJump = 0;
		outDashPoke->DblJumpTouchNum = 0;
	}

	//ジャンプエフェクト位置更新
	{
		VecFx32 vec;
		const VecFx32 *cvec;
		CLACT_WORK_PTR act_ptr;
		act_ptr = PkthlnClAct_GetClActWorkPtr( outDashPoke->ShiftPtr );
		cvec = CLACT_GetMatrix( act_ptr );
		vec = *cvec;
		vec.y = outDashPoke->ShiftEffPos*FX32_ONE;
		CLACT_SetMatrix( act_ptr, &vec );
	}
	//ブーストエフェクト
	{
		int x,y;
		VecFx32 vec;
		const VecFx32 *cvec;
		CLACT_WORK_PTR act_ptr;
		PokeAct_GetPos(outDashPoke->PokeActPtr, &x, &y );
		act_ptr = PkthlnClAct_GetClActWorkPtr( outDashPoke->BoostPtr );
		cvec = CLACT_GetMatrix( act_ptr );
		vec = *cvec;
		vec.y = y*FX32_ONE;
		CLACT_SetMatrix( act_ptr, &vec );
	}

}

//--------------------------------------------------------------------------------------------
/**
 * @brief	ヒットチェック関数
 *
 * @param	inY		Y座標
 * @param	inRange	半径
 * @param	inRect	矩形データ
 *
 * @return	BOOL	TRUE：ヒット	FALSE：ミス
 */
//--------------------------------------------------------------------------------------------
static BOOL CheckHit(const int inY, const u8 inRange, const HIT_RECT *inRect)
{
	BOOL rc = FALSE;

	int top = inY-inRange;
	int bottom = inY+inRange;

	//判定
	if ( ( top <= inRect->Y+inRect->H ) && ( inRect->Y <= bottom ) ){
		rc = TRUE;
	}
	return rc;
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	ヒットチェック関数
 *
 * @param	inY		Y座標
 * @param	inRect	矩形データ
 *
 * @return	BOOL	TRUE：ヒット	FALSE：ミス
 */
//--------------------------------------------------------------------------------------------
static BOOL CheckBoost(const int inY, const HIT_RECT *inRect)
{
	BOOL rc = FALSE;

	//判定	Yだけ判定する
	if ( (inY >= inRect->Y+inRect->H)&&(inY-BOOST_SPACE < inRect->Y+inRect->H) ){
		rc = TRUE;
	}

	return rc;
}

enum{
	SCR_TRANS_NONE,
//	SCR_TRANS_START_VANISHED,
//	SCR_TRANS_SPART,
	SCR_TRANS_GOAL,
	SCR_TRANS_GOAL_AFTER,
	SCR_TRANS_END,
};

//----------------------------------------------------------------------------
/**
 *	@brief	スクリーン転送処理
 *
 *	@param	*bgl			BGL
 *	@param	*ioLane			レーンデータポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void TransScreen(GF_BGL_INI *bgl, HURDLE_LANE *ioLane)
{
	u16 data;
	switch (ioLane->ScrTransState){
	case SCR_TRANS_NONE:	//スタートライン消し作業がまだ
		//走行距離がスタートラインが見えなくなるところまで到達した
		if (ioLane->RunLength >= 96+16){
			data = 2;
			data += (1<<10);		//Hフリップ
			//スタートライン消し
			OS_Printf("今からスタートラインを消す\n");
			//メイン
			GF_BGL_ScrFill( bgl, ioLane->MainFrameNo, 2, 2+ioLane->LaneNo*10, 50, 1, 2, GF_BGL_SCRWRT_PALNL );
			GF_BGL_ScrFill( bgl, ioLane->MainFrameNo, 3, 2+ioLane->LaneNo*10+1, 50, 6, 2, GF_BGL_SCRWRT_PALNL );
			GF_BGL_ScrFill( bgl, ioLane->MainFrameNo, data, 2+ioLane->LaneNo*10+7, 50, 1, 2, GF_BGL_SCRWRT_PALNL );
			//サブ
			GF_BGL_ScrFill( bgl, ioLane->SubFrameNo, 2, 2+ioLane->LaneNo*10, 50, 1, 2, GF_BGL_SCRWRT_PALNL );
			GF_BGL_ScrFill( bgl, ioLane->SubFrameNo, 3, 2+ioLane->LaneNo*10+1, 50, 6, 2, GF_BGL_SCRWRT_PALNL );
			GF_BGL_ScrFill( bgl, ioLane->SubFrameNo, data, 2+ioLane->LaneNo*10+7, 50, 1, 2, GF_BGL_SCRWRT_PALNL );

			GF_BGL_LoadScreenV_Req(bgl, ioLane->MainFrameNo);
			GF_BGL_LoadScreenV_Req(bgl, ioLane->SubFrameNo);
			//スタートライン消した
			ioLane->ScrTransState = SCR_TRANS_GOAL;
			//次のシーケンスのためのフィルポイントセット
			{
				ioLane->OldFillPoint = 255;
			}
		}
		break;
	case SCR_TRANS_GOAL:
		if (ioLane->RunLength-HIDE_OFS >= LANE_LENGTH-GOAL_LINE_OFS){	//	ゴール
			int len = ioLane->RunLength - HIDE_OFS;
			int ofs_chr = (len/8)%64;
			int base = ( 64 - ofs_chr )%64;
			int fill = base - 2;		//幅分のオフセット(63ch・0chまたぎに対応しなくてはダメかも＞OKぽい)
			if (fill < 0){
				fill = 64 + fill;
			}

			ioLane->FillPoint = fill;
			//メイン
			GF_BGL_ScrFill( bgl, ioLane->MainFrameNo, 96, 2+ioLane->LaneNo*10, ioLane->FillPoint, 1, 2, GF_BGL_SCRWRT_PALNL );
			GF_BGL_ScrFill( bgl, ioLane->MainFrameNo, 97, 2+ioLane->LaneNo*10+1, ioLane->FillPoint, 6, 2, GF_BGL_SCRWRT_PALNL );
			GF_BGL_ScrFill( bgl, ioLane->MainFrameNo, 98, 2+ioLane->LaneNo*10+7, ioLane->FillPoint, 1, 2, GF_BGL_SCRWRT_PALNL );
			//サブ
			GF_BGL_ScrFill( bgl, ioLane->SubFrameNo, 96, 2+ioLane->LaneNo*10, ioLane->FillPoint, 1, 2, GF_BGL_SCRWRT_PALNL );
			GF_BGL_ScrFill( bgl, ioLane->SubFrameNo, 97, 2+ioLane->LaneNo*10+1, ioLane->FillPoint, 6, 2, GF_BGL_SCRWRT_PALNL );
			GF_BGL_ScrFill( bgl, ioLane->SubFrameNo, 98, 2+ioLane->LaneNo*10+7, ioLane->FillPoint, 1, 2, GF_BGL_SCRWRT_PALNL );

			GF_BGL_LoadScreenV_Req(bgl, ioLane->MainFrameNo);
			GF_BGL_LoadScreenV_Req(bgl, ioLane->SubFrameNo);
			ioLane->ScrTransState = SCR_TRANS_GOAL_AFTER;
		}
		break;
	case SCR_TRANS_GOAL_AFTER:
		if (ioLane->RunLength-HIDE_OFS >= LANE_LENGTH-GOAL_LINE_OFS+512){	//	ゴールライン消し
			int len = ioLane->RunLength - HIDE_OFS;
			int ofs_chr = (len/8)%64;
			int base = ( 64 - ofs_chr )%64;
			int fill = base - 2;		//幅分のオフセット(63ch・0chまたぎに対応しなくてはダメかも。＞OKぽい)
			if (fill < 0){
				fill = 64 + fill;
			}

			ioLane->FillPoint = fill;
			data = 2;
			data += (1<<10);		//Hフリップ
			//メイン
			GF_BGL_ScrFill( bgl, ioLane->MainFrameNo, 2, 2+ioLane->LaneNo*10, ioLane->FillPoint, 1, 2, GF_BGL_SCRWRT_PALNL );
			GF_BGL_ScrFill( bgl, ioLane->MainFrameNo, 3, 2+ioLane->LaneNo*10+1, ioLane->FillPoint, 6, 2, GF_BGL_SCRWRT_PALNL );
			GF_BGL_ScrFill( bgl, ioLane->MainFrameNo, data, 2+ioLane->LaneNo*10+7, ioLane->FillPoint, 1, 2, GF_BGL_SCRWRT_PALNL );
			//サブ
			GF_BGL_ScrFill( bgl, ioLane->SubFrameNo, 2, 2+ioLane->LaneNo*10, ioLane->FillPoint, 1, 2, GF_BGL_SCRWRT_PALNL );
			GF_BGL_ScrFill( bgl, ioLane->SubFrameNo, 3, 2+ioLane->LaneNo*10+1, ioLane->FillPoint, 6, 2, GF_BGL_SCRWRT_PALNL );
			GF_BGL_ScrFill( bgl, ioLane->SubFrameNo, data, 2+ioLane->LaneNo*10+7, ioLane->FillPoint, 1, 2, GF_BGL_SCRWRT_PALNL );

			GF_BGL_LoadScreenV_Req(bgl, ioLane->MainFrameNo);
			GF_BGL_LoadScreenV_Req(bgl, ioLane->SubFrameNo);
			ioLane->ScrTransState = SCR_TRANS_END;
		}

		break;
	}

}

//--------------------------------------------------------------------------------------------
/**
 * @brief	通信データ関連メイン処理
 * @param	work		ポケスロンポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void CommMain(PKTHLN_PTR work)
{
	int i,j;
	PKTHLN_HURDLE_PTR ptr;
	HURDLE_CHILD_DATA *child_data;
	COMM_EVENT_COMMON_DATA *data;

	ptr = PTFrame_GetEventWorkPtr(work);
	data = PTFrame_GetEvtComCmnData(work);

	//子データの先頭ポインタを取得
	child_data = PKTHLN_CommPack_GetData(&data->SendData);
	//データ加工
	for(i=0;i<HURDLE_EVENT_POKE_NUM;i++){
		//位置セット
		child_data->Len[i] = ptr->Lane[i].RunLength;
		if ( (ptr->Lane[i].Finished)&&(!child_data->Goal[i]) ){	//ゴールした瞬間
			child_data->Goal[i] = 1;
			//タイムセット
			child_data->Time[i] = ptr->GameTime;
		}
	}

	//親動作
	if ( PTFrameGetCurrentID(work) == COMM_PARENT_ID ){
		u8 finish = 0;
		//メイン

		//共有(親)データ加工
		HURDLE_CHILD_DATA *child;
		HURDLE_PARENT_DATA *parent;
		parent = PKTHLN_CommPack_GetData(&data->SendShareData);

		//親データは直接レシーバにセット
		{
			HURDLE_CHILD_DATA *child_rec;

			child_rec = PKTHLN_CommPack_GetData(&data->ReciveData[0]);
			child = PKTHLN_CommPack_GetData(&data->SendData);
			(*child_rec) = (*child);
		}

		for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
			child = PKTHLN_CommPack_GetData(&data->ReciveData[i]);
			for(j=0;j<HURDLE_EVENT_POKE_NUM;j++){
				parent->Len[i][j] = child->Len[j];
				///parent->State[i][j] = 0;
			}
			//終了チェック
			if (child->Finish){
				finish++;
			}
		}
		if (finish == PTFrame_GetPlayerNum(work)){
			parent->Finish = 1;		//NPC以外終了
			OS_Printf("NPC以外ゴールした:%d\n",parent->Finish);
		}
		//現在順位算出
		CalcRank(work);
	}

	//通信関連描画準備
	SetDraw(work);
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	ポジションのコントロール
 * @param	ptr			競技ポインタ
 * @param	parent		親通信データ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void PositionCont(PKTHLN_HURDLE_PTR ptr, HURDLE_PARENT_DATA *parent)
{
	int i,j;

	NODE node[TOTAL_POKE_NUM+1];	//0番目ノードは開始ポインタ監視用のダミー

	//準備
	node[0].Prev = NULL;
	node[0].Next = &node[1];
	node[0].Item.Rank = 0;
	node[0].Item.Index = 0;

	//全プレーヤのポケモンのソート
	for(i=0;i<TOTAL_POKE_NUM;i++){
		u8 rank;
		u8 idx;
		u8 shift;
		NODE *now;
		NODE *target;
		//ノード取得
		now = &node[i+1];
		//順位取得
		idx = i/2;
		shift = i%2;
		//値セット
		rank = (parent->Rank[idx] >> (4*shift)) & 0x0f;		//4ビットマスク
		now->Item.Rank = rank;
		now->Item.Index = i;
		now->Next = NULL;

		target = &node[0];
		for(j=0;j<i;j++){
			target = target->Next;
			//挿入
			if (target->Item.Rank > now->Item.Rank){	//先に進んでいる
				//リストの前に追加
				target->Prev->Next = now;
				now->Prev = target->Prev;
				now->Next = target;
				target->Prev = now;
				break;
			}else if( (target->Item.Rank == now->Item.Rank)&&
					(target->Item.Index > now->Item.Index) ){	//距離同じでも、インデックスが若い
				//リストの前に追加
				target->Prev->Next = now;
				now->Prev = target->Prev;
				now->Next = target;
				target->Prev = now;
				break;
			}
		}
		if (j==i){
			//リスト最後に追加
			target->Next = now;
			now->Prev = target;
		}
	}

	//ポジションセット
	{
		NODE *now;
		//表示
		HurdlePokeIcon_SetAllVanish(ptr->HpiCntPtr, 1);
		now = &node[0];
		for(i=0;i<TOTAL_POKE_NUM;i++){
			int disp;
			u8 rank;
			now = now->Next;
			rank = now->Item.Rank;
			if (rank > RANK_DISP_MAX){
				rank = RANK_DISP_MAX;
			}
			disp = ICON_HALF_SIZE + (ICON_HALF_SIZE * 2 * i);
			HurdlePokeIcon_SetPosition(ptr->HpiCntPtr, now->Item.Index, disp);
			HurdlePokeIcon_SetRank(ptr->HpiCntPtr, now->Item.Index, rank);	//順位セット
			HurdlePokeIcon_SetVanish(ptr->HpiCntPtr, now->Item.Index, 1);	//表示
		}
	}
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	通信描画
 * @param	work		ポケスロンポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetDraw(PKTHLN_PTR work)
{
	u8 i;
	COMM_EVENT_COMMON_DATA * data;
	HURDLE_PARENT_DATA *parent;
	PKTHLN_HURDLE_PTR ptr = PTFrame_GetEventWorkPtr(work);

	data = PTFrame_GetEvtComCmnData(work);
	parent = PKTHLN_CommPack_GetData(&data->ReciveShareData);

	if (ptr->DrawCounterStart){
		ptr->DrawRankFrame++;
	}

	//初回フラグ成立前
	if (!ptr->FirstDrawFlg){
		if (ptr->DrawRankFrame >= FIRST_DRAW_RANK_FRAME){
			ptr->DrawRankFrame = 0;
			//初回フラグを立てる
			ptr->FirstDrawFlg = 1;
			//アイコンポジションセット
			PositionCont(ptr, parent);
			//順位表示
			for (i=0;i<HURDLE_EVENT_POKE_NUM;i++){
				u8 rank;
				CLACT_WORK_PTR act_ptr;
				u8 idx;
				u8 shift;
				act_ptr = PkthlnClAct_GetClActWorkPtr( ptr->Lane[i].DashPoke.RankPtr );
				//表示開始
				PkthlnClAct_SetActive(ptr->Lane[i].DashPoke.RankPtr, 1, 1);

				idx = (PTFrameGetCurrentID(work)*HURDLE_EVENT_POKE_NUM+i)/2;
				shift = (PTFrameGetCurrentID(work)*HURDLE_EVENT_POKE_NUM+i)%2;
				//自分の順位取得
				rank = (parent->Rank[idx] >> (4*shift)) & 0x0f;	//4ビットマスク
				OS_Printf("%d:my_rank=%d\n",i,rank);
				GF_ASSERT( (0<rank)&&(rank<=TOTAL_POKE_NUM) );

				{
					VecFx32 scale;
					//アニメ開始
					ptr->Lane[i].RankScale = 1.5;
					scale.x = ptr->Lane[i].RankScale * FX32_ONE;
					scale.y = ptr->Lane[i].RankScale * FX32_ONE;
					scale.z = ptr->Lane[i].RankScale * FX32_ONE;
					//順位セット
					ptr->Lane[i].LocalRank = rank;
					//スケールセット
					CLACT_SetScale(act_ptr, &scale);
					//順位変更
					CLACT_AnmChg( act_ptr, rank-1 );
				}
			}
		}
	}else{
		if (ptr->DrawRankFrame >= DRAW_RANK_FRAME){
			ptr->DrawRankFrame = 0;
			//アイコンポジションセット
			PositionCont(ptr, parent);
			//順位表示
			for (i=0;i<HURDLE_EVENT_POKE_NUM;i++){
				u8 rank;
				CLACT_WORK_PTR act_ptr;
				u8 idx;
				u8 shift;
				act_ptr = PkthlnClAct_GetClActWorkPtr( ptr->Lane[i].DashPoke.RankPtr );
				idx = (PTFrameGetCurrentID(work)*HURDLE_EVENT_POKE_NUM+i)/2;
				shift = (PTFrameGetCurrentID(work)*HURDLE_EVENT_POKE_NUM+i)%2;
				//自分の順位取得
				rank = (parent->Rank[idx] >> (4*shift)) & 0x0f;	//4ビットマスク
				OS_Printf("%d:my_rank=%d\n",i,rank);
				GF_ASSERT( (0<rank)&&(rank<=TOTAL_POKE_NUM) );

				//ゴールしている場合
				if (ptr->Lane[i].Finished){
					//順位表示位置変更
					VecFx32 vec;
					vec = *CLACT_GetMatrix(act_ptr);
					vec.y = GOAL_RANK_DISP_POS * FX32_ONE;
					CLACT_SetMatrix( act_ptr, &vec );
					CLACT_AnmChg( act_ptr, GOAL_ANM_OFS + rank-1 );
				}

				//現在保持している順位と違うならアニメ
				if (ptr->Lane[i].LocalRank != rank){
					VecFx32 scale;
					if (ptr->Lane[i].Finished){
						OS_Printf("順位が入れ替わった%d:%d→%d\n",i,ptr->Lane[i].LocalRank,rank);
					}
					//順位セット
					ptr->Lane[i].LocalRank = rank;

					if (!ptr->Lane[i].Finished){
						//アニメ開始
						ptr->Lane[i].RankScale = 1.5;
						scale.x = ptr->Lane[i].RankScale * FX32_ONE;
						scale.y = ptr->Lane[i].RankScale * FX32_ONE;
						scale.z = ptr->Lane[i].RankScale * FX32_ONE;
						//スケールセット
						CLACT_SetScale(act_ptr, &scale);
						//順位変更
						CLACT_AnmChg( act_ptr, rank-1 );
					}
				}
			}
		}
	}

	for (i=0;i<HURDLE_EVENT_POKE_NUM;i++){
		VecFx32 scale;
		const VecFx32 *vec;
		CLACT_WORK_PTR act_ptr;
		act_ptr = PkthlnClAct_GetClActWorkPtr( ptr->Lane[i].DashPoke.RankPtr );

		vec = CLACT_GetScale(act_ptr);
		if ( vec->x > FX32_ONE ){//アニメ中か？
			ptr->Lane[i].RankScale -= 0.1;	//アニメ
		}else{
			ptr->Lane[i].RankScale = 1.0;	//アニメ
		}
		scale.x = ptr->Lane[i].RankScale * FX32_ONE;
		scale.y = ptr->Lane[i].RankScale * FX32_ONE;
		scale.z = ptr->Lane[i].RankScale * FX32_ONE;
		//スケールセット
		CLACT_SetScale(act_ptr, &scale);
	}

////////////////////////
#if 0

	if (ptr->DrawRankFrame >= DRAW_RANK_FRAME){
		ptr->DrawRankFrame = 0;

		//アイコンポジションセット
		PositionCont(ptr, parent);

		//順位表示
		for (i=0;i<HURDLE_EVENT_POKE_NUM;i++){
			u8 rank;
			CLACT_WORK_PTR act_ptr;
			u8 idx;
			u8 shift;
			act_ptr = PkthlnClAct_GetClActWorkPtr( ptr->Lane[i].DashPoke.RankPtr );
			idx = (PTFrameGetCurrentID(work)*HURDLE_EVENT_POKE_NUM+i)/2;
			shift = (PTFrameGetCurrentID(work)*HURDLE_EVENT_POKE_NUM+i)%2;
			//自分の順位取得
			rank = (parent->Rank[idx] >> (4*shift)) & 0x0f;	//4ビットマスク
			OS_Printf("%d:my_rank=%d\n",i,rank);
			GF_ASSERT( (0<rank)&&(rank<=TOTAL_POKE_NUM) );

			//ゴールしている場合
			if (ptr->Lane[i].Finished){
				//順位表示位置変更
				VecFx32 vec;
				vec = *CLACT_GetMatrix(act_ptr);
				vec.y = GOAL_RANK_DISP_POS * FX32_ONE;
				CLACT_SetMatrix( act_ptr, &vec );
				CLACT_AnmChg( act_ptr, GOAL_ANM_OFS + rank-1 );
			}


			//現在保持している順位と違うならアニメ
			if (ptr->Lane[i].LocalRank != rank){
				VecFx32 scale;
				if (ptr->Lane[i].Finished){
					OS_Printf("順位が入れ替わった%d:%d→%d\n",i,ptr->Lane[i].LocalRank,rank);
				}
				//アニメ開始
				ptr->Lane[i].RankScale = 1.5;
				scale.x = ptr->Lane[i].RankScale * FX32_ONE;
				scale.y = ptr->Lane[i].RankScale * FX32_ONE;
				scale.z = ptr->Lane[i].RankScale * FX32_ONE;
				//順位セット
				ptr->Lane[i].LocalRank = rank;
				//スケールセット
				CLACT_SetScale(act_ptr, &scale);
				//順位変更
				CLACT_AnmChg( act_ptr, rank-1 );
			}else{
				VecFx32 scale;
				const VecFx32 *vec;
				vec = CLACT_GetScale(act_ptr);
				if ( vec->x > FX32_ONE ){//アニメ中か？
					ptr->Lane[i].RankScale -= 0.1;	//アニメ
				}else{
					ptr->Lane[i].RankScale = 1.0;	//アニメ
				}
				scale.x = ptr->Lane[i].RankScale * FX32_ONE;
				scale.y = ptr->Lane[i].RankScale * FX32_ONE;
				scale.z = ptr->Lane[i].RankScale * FX32_ONE;
				//スケールセット
				CLACT_SetScale(act_ptr, &scale);
			}
		}
	}else{
		ptr->DrawRankFrame++;
	}
#endif
	DispTime(ptr);
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	ランキング計算
 * @param	work		ポケスロンポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void CalcRank(PKTHLN_PTR work)
{
	R_NODE node[TOTAL_POKE_NUM+1];	//0番目ノードは開始ポインタ監視用のダミー
	HURDLE_CHILD_DATA *child;
	HURDLE_PARENT_DATA *parent;
	int i,j,k;
	COMM_EVENT_COMMON_DATA *data;
	data = PTFrame_GetEvtComCmnData(work);
	parent = PKTHLN_CommPack_GetData(&data->SendShareData);

	//準備
	node[0].Prev = NULL;
	node[0].Next = &node[1];
	node[0].Item.Len = 0;
	node[0].Item.Index = 0;
	node[0].Item.Time = 0;
	node[0].Item.Goal = FALSE;
	node[0].Item.TakingOver = FALSE;


	for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
		child = PKTHLN_CommPack_GetData(&data->ReciveData[i]);
		for(j=0;j<HURDLE_EVENT_POKE_NUM;j++){
			int count;
			R_NODE *now;
			R_NODE *target;
			count = i*HURDLE_EVENT_POKE_NUM+j;
			//ノード取得
			now = &node[count+1];
			//値セット
			now->Item.Len = child->Len[j];
			now->Item.Time = child->Time[j];
			now->Item.Index = count;
			now->Item.Goal = child->Goal[j];
			now->Item.TakingOver = FALSE;
			now->Next = NULL;

			target = &node[0];

			if (now->Item.Goal){
				OS_Printf("%d:ゴールした\n",count);
			}

			for(k=0;k<count;k++){
				BOOL rc;
				target = target->Next;
				if (now->Item.Goal){
					rc = SortTime(now, target);
				}else{
					rc = SortLen(now, target);
				}
				if (rc){
					break;
				}
			}	//end for
			if (k==count){
				//リスト最後に追加
				target->Next = now;
				now->Prev = target;
			}
		}
	}

	//12体のポケの順位を送信データに格納
	{
		u8 rank;
		u8 rnk_stck;
		R_NODE *target;
#ifdef PM_DEBUG
		u8 debug[TOTAL_POKE_NUM];

		for(i=0;i<TOTAL_POKE_NUM;i++){
			debug[i] = 0;
		}
#endif
		target = &node[0];
		rank = 0;
		rnk_stck = 1;

		//送信順位データをクリア
		for (i=0;i<6;i++){
			parent->Rank[i] = 0;
		}

		for(i=0;i<TOTAL_POKE_NUM;i++){
			target = target->Next;
			if (target == NULL){
				OS_Printf("%d:データがＮＵＬＬ\n",i);
				GF_ASSERT(0);
			}

			//ランクを上げるかをチェックし必要であればランクを上げる
			if (!target->Item.TakingOver){
				rank += rnk_stck;
				rnk_stck = 1;
			}else{
				rnk_stck++;
			}

			OS_Printf("%d:rank = %d Len = %d Time = %d\n",target->Item.Index, rank, target->Item.Len, target->Item.Time);
#ifdef PM_DEBUG
			debug[target->Item.Index] = 1;
#endif
			//データセット
			SetRankToCommData(parent, target->Item.Index, rank);
		}
#ifdef PMDEBUG
		for(i=0;i<TOTAL_POKE_NUM;i++){
			if (!debug[i]){
				OS_Printf("%d：ランキングに入ってない\n",i);
				GF_ASSERT(0);
			}
		}
#endif
	}
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	リスト追加　自分がゴールしている場合(時間でソート)
 * @param	now			自分
 * @param	target		比較対象
 *
 * @return	BOOL リストの前に追加できた場合TRUE
 */
//--------------------------------------------------------------------------------------------
static BOOL SortTime(R_NODE *now, R_NODE *target)
{
	//比較対象はゴールしているか？
	if (target->Item.Goal){	//ゴールしてる
		//時間が早いほうが前
		if (target->Item.Time > now->Item.Time){
			//リストの前に追加
			target->Prev->Next = now;
			now->Prev = target->Prev;
			now->Next = target;
			target->Prev = now;
			return TRUE;
		}else if( target->Item.Time == now->Item.Time ){
			if (target->Item.Index > now->Item.Index ){	//時間同じでも、インデックスが若い
				//リストの前に追加
				target->Prev->Next = now;
				now->Prev = target->Prev;
				now->Next = target;
				target->Prev = now;
				target->Item.TakingOver = TRUE;	//前方リストデータと記録が同じなので、順位を引き継ぐ
				return TRUE;
			}else{
				//前方リストデータと記録が同じなので、順位を引き継ぐ
				now->Item.TakingOver = TRUE;
			}
		}
	}else{	//ゴールしていない
		//無条件でリストの前に追加
		target->Prev->Next = now;
		now->Prev = target->Prev;
		now->Next = target;
		target->Prev = now;
		return TRUE;
	}

	return FALSE;
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	リスト追加　自分がゴールしていない場合(走行距離でソート)
 * @param	now			自分
 * @param	target		比較対象
 *
 * @return	BOOL リストの前に追加できた場合TRUE
 */
//--------------------------------------------------------------------------------------------
static BOOL SortLen(R_NODE *now, R_NODE *target)
{
	if (target->Item.Len < now->Item.Len){	//先に進んでいる
		//リストの前に追加
		target->Prev->Next = now;
		now->Prev = target->Prev;
		now->Next = target;
		target->Prev = now;
		return TRUE;
	}else if (target->Item.Len == now->Item.Len){
		if ( target->Item.Time > now->Item.Time ){	//時間のかかっていない方が速いとみなす
			//リストの前に追加
			target->Prev->Next = now;
			now->Prev = target->Prev;
			now->Next = target;
			target->Prev = now;
			return TRUE;
		}else if( target->Item.Time == now->Item.Time ){
			if (target->Item.Index > now->Item.Index ){	//時間同じでも、インデックスが若い
				//リストの前に追加
				target->Prev->Next = now;
				now->Prev = target->Prev;
				now->Next = target;
				target->Prev = now;
				target->Item.TakingOver = TRUE;	//前方リストデータと記録が同じなので、順位を引き継ぐ
				return TRUE;
			}else{
				now->Item.TakingOver = TRUE;	//前方リストデータと記録が同じなので、順位を引き継ぐ
			}
		}
	}

	return FALSE;
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	通信データにランキングデータをセット
 * @param	parent			親通信データ
 * @param	inIdx			参加ポケモンインデックス
 * @param	inRnk			ランキング
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetRankToCommData(HURDLE_PARENT_DATA *parent, const u8 inIdx, const u8 inRank)
{
	u8 data;
	u8 point;
	u8 shift;
	GF_ASSERT(inIdx < TOTAL_POKE_NUM);
	GF_ASSERT( (0<inRank)&&(inRank<=TOTAL_POKE_NUM) );
	//書き込む場所を検出
	point = inIdx/2;
	shift = inIdx%2;

	data = ( inRank<<(4*shift) );

	parent->Rank[point] |= data;
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	ゴール後歩行処理終了チェック
 * @param	ptr		競技アプリポインタ
 *
 * @return	TRUE:終了		FALSE:継続
 */
//--------------------------------------------------------------------------------------------
static BOOL CheckGoalMoveEnd(PKTHLN_HURDLE_PTR ptr)
{
	//自分のポケモンがゴール後歩行を終了したかをチェックする
	int i;
	BOOL rc = FALSE;

	for(i=0;i<HURDLE_EVENT_POKE_NUM;i++){
		if (ptr->Lane[i].DashPoke.State != D_POKE_ST_FINISHED){
			break;
		}
	}

	if (i==HURDLE_EVENT_POKE_NUM){
		rc = TRUE;
	}

	return rc;
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	NPC行動
 * @param	work		ポケスロンポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void MoveNPC(PKTHLN_PTR work)
{
	PKTHLN_HURDLE_PTR ptr;
	HURDLE_CHILD_DATA *child;
	COMM_EVENT_COMMON_DATA *data;
	int player_num;
	int i,j;

	//親でなければ、処理しない
	if ( PTFrameGetCurrentID(work) != COMM_PARENT_ID ){
		return;
	}

	data = PTFrame_GetEvtComCmnData(work);
	ptr = PTFrame_GetEventWorkPtr(work);
	player_num = PTFrame_GetPlayerNum(work);

	//NPC処理(NPCのレシーブデータに値を格納)
	for(i=player_num;i<ENTRY_MEMBER_NUM_MAX;i++){
		child = PKTHLN_CommPack_GetData(&data->ReciveData[i]);
		for(j=0;j<HURDLE_EVENT_POKE_NUM;j++){
			u8 idx;
			idx = (i-player_num)*ENTRY_MAX+j;
			MoveNPCCore(work, ptr, child, i, j, idx);
		}
	}
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	障害物のジェネレート
 * @param	ptr		競技アプリポインタ
 * @param	inLength	走行距離
 * @param	inLane		レーン番号
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void GenerateObst(PKTHLN_HURDLE_PTR ptr, const int inLength, const u8 inLane)
{

	//現在の走行距離から、生成するかどうかを判定する
	int len;
	int disp_blank = (DISP_BLANK / 8);
	len = inLength + (24+8+disp_blank)*8;	//走行距離+画面上までの距離(サブ24キャラ、メイン8キャラ、ブランク分キャラ)
	//ジェネレータに走行距離を渡して、生成開始
	H_OBST_GENE_Generate(ptr->ObstGenePtr, len, inLane);
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	土煙のジェネレート
 * @param	ptr		競技アプリポインタ
 * @param	ioLame		レーンポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void GenerateSmog(PKTHLN_HURDLE_PTR ptr, HURDLE_LANE *ioLane)
{
	int x_array[HURDLE_EVENT_POKE_NUM] = {
		RANE1_POKE_X,RANE2_POKE_X,RANE3_POKE_X
	};
	int frame;

	//ジャンプ中は煙でない
	if (ioLane->DashPoke.State == D_POKE_ST_JUMP){
		return;
	}
	//ゴールしたら煙出ない
	if ( ioLane->Finished){
		return;
	}

	if ( ioLane->DashPoke.State == D_POKE_ST_PENALTY_DOWN ){
		frame = SMOG_PENALTY_FRAME;
	}else{
		switch(ioLane->Boost){
		case NO_BOOST:
			frame = SMOG_FRAME1;
			break;
		case BOOST1:
			frame = SMOG_FRAME2;
			break;
		case BOOST2:
			frame = SMOG_FRAME3;
			break;
		case BOOST3:
			frame = SMOG_FRAME4;
			break;
		case BOOST4:
			frame = SMOG_FRAME5;
			break;
		default:
			GF_ASSERT(0);
			frame = SMOG_FRAME1;
		}
	}

	ioLane->SmogCounter++;
	if (ioLane->SmogCounter >= frame){
		VecFx32 vec = {0,0,0};
		int x,y;
		ioLane->SmogCounter = 0;
		//ポケの影の位置を取得
		vec.x = ( x_array[ioLane->LaneNo]+(gf_rand()%7-3) ) *FX32_ONE;		//Ｘ座標は出る位置にばらつきを出す
		vec.y = (MS_BG_OFS+RANE_POKE_Y)*FX32_ONE;
		H_SMOG_GENE_Generate(ptr->SmogGenePtr, ioLane->LaneNo, &vec );
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケモンをタッチしているかを判定する(この競技限定の矩形判定)
 *
 *	@param	ptr			競技ワークポインタ
 *	@param	u16 inX		Ｘ座標
 *	@param	u16 inY		Ｙ座標
 *
 *	@return 	u8 	タッチしたポケインデックス	（タッチしていないときはJUMP_EVENT_POKE_NUM）
 */
//-----------------------------------------------------------------------------
static u8 CheckPokeTouch(PKTHLN_HURDLE_PTR ptr, const u16 inX, const u16 inY)
{
	u8 i;
	int x_array[HURDLE_EVENT_POKE_NUM] = {
		RANE1_POKE_X,RANE2_POKE_X,RANE3_POKE_X
	};

	for(i=0;i<HURDLE_EVENT_POKE_NUM;i++){
		//矩形判定
		int sx = x_array[i]-(TOUCH_W/2);
		int sy = TOUCH_Y;

		if ( ((sx<inX)&&(inX<sx+TOUCH_W)) &&
			 ((sy<inY)&&(inY<sy+TOUCH_H)) ){
			//タッチしている
			OS_Printf("%dのポケにタッチ\n",i);
			return i;
		}
	}
	return HURDLE_EVENT_POKE_NUM;
}

//----------レコードＢＭＰ---------------
//ＢＮＰウィンドウデータ
static const BMPWIN_DAT RecordBmpData = {
		REC_BG, WIN_REC_PX, WIN_REC_PY,
		WIN_REC_SX, WIN_REC_SY, REC_FONT_PAL, WIN_REC_CGX
};

//--------------------------------------------------------------------------------------------
/**
 * BMPウィンドウ追加
 *
 * @param 	ptr			コントローラポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void CreateBmpWin( PKTHLN_HURDLE_PTR ptr )
{
	const BMPWIN_DAT * dat = &RecordBmpData;

	GF_BGL_BmpWinAddEx( ptr->bgl, &ptr->Win, dat );

	//先頭キャラをクリア（スクリーンクリアされてるところは、このキャラで埋まる）
	GF_BGL_CharFill( ptr->bgl, REC_BG, 0, 1, 0 );

	//システム用フォントパレット転送
	SystemFontPaletteLoad(PALTYPE_MAIN_BG, REC_FONT_PAL*32, ptr->HeapID);

	GF_BGL_BmpWinDataFill( &ptr->Win, 0 );
}

//----------------------------------------------------------------------------
/**
 *	@brief		レコード文字列展開
 *
 *	@param	ptr		コントローラポインタ
 *	@param	inTime		タイム
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void SetRecordStr(PKTHLN_HURDLE_PTR ptr, const int inTime)
{
	WORDSET *word;
	STRBUF * str;
	MSGDATA_MANAGER *msgman;
	int integer;
	int decimal;

	//整数部分
	integer = inTime / 30;
	//小数部分
	decimal = ((inTime % 30) *10 ) / 30;

	msgman = MSGMAN_Create(MSGMAN_TYPE_DIRECT, ARC_MSG, NARC_msg_pokethlon_dat, ptr->HeapID);
    word = WORDSET_Create(ptr->HeapID);
	WORDSET_RegisterNumber(word, 0, integer, 3,
				NUMBER_DISPTYPE_LEFT,NUMBER_CODETYPE_DEFAULT);
	WORDSET_RegisterNumber(word, 1, decimal, 1,
				NUMBER_DISPTYPE_LEFT,NUMBER_CODETYPE_DEFAULT);

    str = MSGDAT_UTIL_AllocExpandString(word, msgman, msg_pkthln_new_record01, ptr->HeapID);

	GF_STR_PrintColor( 	&ptr->Win, FONT_TOUCH, str,
					0, 0, MSG_NO_PUT, COL_N_WHITE, NULL );
	STRBUF_Delete(str);//<一括表示なので、メモリをここで消してもOK
	WORDSET_Delete( word );
	MSGMAN_Delete( msgman );

	GF_BGL_BmpWinOn(&ptr->Win);
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケモンジャンプ中拡縮処理
 *
 *	@param	outDashPoke		ポケモンンポインタ
 *	@param	inYOfs			Yオフセット
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void SetPokeScale(HURDLE_POKE *outDashPoke, const int inYOfs)
{
	int ofs;
	float scale;

	ofs = inYOfs;
	if (ofs < 0){
		ofs = 0;
	}

	//拡縮率算出	拡縮率　＝　((ofs x 2) + 100 )％
	scale = ( (ofs*2.0) + 100.0 ) / 100.0;

	OS_Printf("poke_scale=%f\n",scale);

	PokeAct_SetScale(outDashPoke->PokeActPtr, scale, scale);
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケモンジャンプ中拡縮処理(ジャンプ値0のポケ用)
 *
 *	@param	outDashPoke		ポケモンンポインタ
 *	@param	inFlg
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void SetNonJmpPokeScale(HURDLE_POKE *outDashPoke, const u8 inFlg)
{
	float scale;

	if (inFlg){			//戻り
		u8 count = outDashPoke->LST.Count-1;
		scale = 100.0 - ((outDashPoke->PokeParam.UpDownFrame-count)*10.0);
	}else{				//潜り
		u8 count = outDashPoke->LST.Count-1;
		//拡縮率算出	拡縮率　＝　((ofs x 2) + 100 )％
		scale = 100.0 - (count*10.0);

		if (scale < 0){
			scale = 10.0;
		}
	}

	scale /= 100.0;

	OS_Printf("poke_scale=%f\n",scale);

	PokeAct_SetScale(outDashPoke->PokeActPtr, scale, scale);
}


//----------------------------------------------------------------------------
/**
 *	@brief	タイマー表示
 *
 *	@param	ptr	コントローラポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void DispTime(PKTHLN_HURDLE_PTR ptr)
{
	u16 time;
	u8 min;
	u8 miri,miri_t;
	u8 sec,sec_t,sec_o;

	time = ptr->MyTime;

	//秒計算
	sec = time / 30;
	//秒以下
	miri = time % 30;
	miri = (miri*100)/30;
	//分計算
	min = sec / 60;
	sec = sec % 60;

	sec_t = sec / 10;
	sec_o = sec % 10;
	miri_t = miri / 10;

	//分を書き換え
	CLACT_AnmChg(ptr->Timer.Number[0], min+1);
	//秒を書き換え
	CLACT_AnmChg(ptr->Timer.Number[2], sec_t+1);
	CLACT_AnmChg(ptr->Timer.Number[3], sec_o+1);
	//小数以下を書き換え
	CLACT_AnmChg(ptr->Timer.Number[5], miri_t+1);
}

//----------------------------------------------------------------------------
/**
 *	@brief	NPC動作		※NPCにはジャンプできないポケモンを設定しないようにするため、ジャンプカウントに判定をいれていない
 *
 *  @param	work		ポケスロンポインタ
 *	@param	ptr			コントローラポインタ
 *	@param	child		子機データポインタ
 *	@param	inNetID		ネットＩＤ
 *	@param	inLane		レーン番号
 *	@param	inDataIdx	NPCデータインデックス
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void MoveNPCCore(PKTHLN_PTR work, PKTHLN_HURDLE_PTR ptr, HURDLE_CHILD_DATA *child,
						const u8 inNetID, const u8 inLane, const u8 inDataIdx)
{
	NPC_DATA_CORE* data;
	data = &ptr->NpcData[inDataIdx];

	//加速処理(ペナルティ中ではない＆ゴールしていない&ブースト中ではない＆ベース速度を超えていない)
	if ( (data->Finished != FINISH_GOAL)&&
		( data->State != D_POKE_ST_PENALTY_DOWN )&&
		 (data->Boost == 0)&&
		 (data->SpeedF < data->BaseSpeed) ){
		data->SpeedF += data->AcceleSpeed;
		if (data->SpeedF > data->BaseSpeed){
			data->SpeedF = data->BaseSpeed;
		}
	}

	if(data->State == D_POKE_ST_PENALTY_DOWN){			//ペナルティー中
		//カウンタをデクリメント
		data->Counter--;
		if (data->Counter <= 0){		//ペナルティー終了
			data->State = D_POKE_ST_NONE;
		}
	}else{					//地面
		int pos;
		//障害物データへアクセスし、データの有無を確認
		pos = H_OBST_GENE_IsObstData(ptr->ObstGenePtr, inLane, data->RunLen);
		if ((pos != -1)&&(data->CheckPos != pos)){	//未チェックの障害物がある
			//ジャンプ判定
			u8 prob = gf_rand()%100;
			if (prob < data->Grate){		//成功ジャンプ
				//ブースト
				if (data->Boost < BOOST_MAX){
					data->Boost++;
					data->SpeedF = data->BaseSpeed + BoostSpeed[data->Boost-1];
				}
				//アクションポイント加算「ダッシュ回数」
				PTFrame_AddActionPoint(	work, inNetID, inLane, ADD_TYPE_DASH, 1 );
				//アクションポイント加算「ジャンプ回数」
				PTFrame_AddActionPoint(	work, inNetID, inLane, ADD_TYPE_JUMP, 1 );
			}else if(prob < data->Bad){	//普通ジャンプ失敗
				//ペナルティ状態
				data->State = D_POKE_ST_PENALTY_DOWN;
				//ペナルティカウントセット
				data->Counter = PENALTY_TIME;
				//ブースト解除
				data->Boost = 0;
				//ペナルティースピードにする
				data->SpeedF = PENALTY_SPEED;
				//アクションポイント加算「失敗回数」
				PTFrame_AddActionPoint(	work, inNetID, inLane, ADD_TYPE_FAIL, 1 );
			}else{		//普通ジャンプ
				//アクションポイント加算「ジャンプ回数」
				PTFrame_AddActionPoint(	work, inNetID, inLane, ADD_TYPE_JUMP, 1 );
			}

			//チェックした障害物の位置を記憶する
			data->CheckPos = pos;
		}
	}

	//走行距離更新
	{
		float temp;
		int speed;
		temp = data->SpeedF+data->RestSpeed;
		speed = temp;
		data->RestSpeed = temp - speed;
		//走行処理加算
		data->RunLen += speed;
	}

	child->Len[inLane] =  data->RunLen;

	//ゴール判定
	if ( (!data->Finished)&&(data->RunLen>=LANE_LENGTH) ){
		child->Goal[inLane] = 1;
		//タイム記憶
		child->Time[inLane] = ptr->GameTime;
		data->Time = ptr->GameTime;
		data->Finished = TRUE;
		//NPCゴールＳＥ
		Snd_SePlay(SE_THLON_NPC_GOAL);
		OS_Printf("ＴＩＭＥ＝%d\n",ptr->GameTime);
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	NPCデータ作成
 *
 *	@param	work		ポケスロンポインタ
 *	@param	inData		ハードル走ポケパラメータポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void MakeNPCCoreData(PKTHLN_PTR work, const HURDLE_PARAM* inData)
{
	u8 i,j;
	PKTHLN_HURDLE_PTR ptr = PTFrame_GetEventWorkPtr(work);
	u8 player_num = PTFrame_GetPlayerNum(work);
	for (i=player_num;i<ENTRY_MEMBER_NUM_MAX;i++){
		for(j=0;j<ENTRY_MAX;j++){
			NPC_DATA_CORE* data;
			const POKE_SPEC *spec;

			u8 idx = (i-player_num)*ENTRY_MAX+j;

			data = &ptr->NpcData[idx];

			//ポケのパラメータセット
			spec = PTFrame_GetPokeSpec(work, i, j);
			//速度関連
			data->BaseSpeed = (float)inData->Speed[spec->Speed]/10;			//値を1/10にして使用
			data->AcceleSpeed = (float)inData->Accele[spec->Technique]/100;	//値を1/100にして使用

			//NPCの確率パターンを抽選
			switch( gf_rand()%NPC_PROB_TYPE_NUM ){
			case 0:
				data->Grate = 10;
				data->Bad = 10+40;
				break;
			case 1:
				data->Grate = 20;
				data->Bad = 20+30;
				break;
			case 2:
				data->Grate = 30;
				data->Bad = 30+30;
				break;
			case 3:
				data->Grate = 20;
				data->Bad = 20+50;
				break;
			case 4:
				data->Grate = 30;
				data->Bad = 30+40;
				break;
			case 5:
				data->Grate = 40;
				data->Bad = 40+40;
				break;
			default:
				GF_ASSERT(0);
			}
		}
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	ブースト
 *
 *  @param	work	ポケスロンワークポインタ
 *	@param	inLane	レーンポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void Boost(PKTHLN_PTR work, HURDLE_LANE *inLane)
{
	if (inLane->Boost < BOOST_MAX){
		CLACT_WORK_PTR act_ptr;
		act_ptr = PkthlnClAct_GetClActWorkPtr( inLane->DashPoke.BoostPtr );
		inLane->Boost++;
		if (inLane->Boost == 1){
			//SE
			Snd_SePlayEx( SE_HURDLE_MOVE1, SndPlayer[inLane->LaneNo] );
			Snd_PanSetByPlayerNo( SndPlayer[inLane->LaneNo], SndPan[inLane->LaneNo] );	//パン設定

			//アニメ速くする
			PokeAct_SetDir(inLane->DashPoke.PokeActPtr, POKE_DIR_UP_LV1);
			//ブースト
			CLACT_AnmChg( act_ptr, BOOST_LV234 );
		}else if(inLane->Boost == BOOST_MAX){
			//SE
			Snd_SePlayEx( SE_HURDLE_MOVE3, SndPlayer[inLane->LaneNo] );
			Snd_PanSetByPlayerNo( SndPlayer[inLane->LaneNo], SndPan[inLane->LaneNo] );	//パン設定
			//アニメ速くする
			PokeAct_SetDir(inLane->DashPoke.PokeActPtr, POKE_DIR_UP_LV2);
			//ブースト
			CLACT_AnmChg( act_ptr, BOOST_LV5 );
		}else if ( (inLane->Boost == 2)||(inLane->Boost == 3) ){
			//SE
			Snd_SePlayEx( SE_HURDLE_MOVE2, SndPlayer[inLane->LaneNo] );
			Snd_PanSetByPlayerNo( SndPlayer[inLane->LaneNo], SndPan[inLane->LaneNo] );	//パン設定
		}

		if (inLane->SpeedF < SPEED_MAX){
			inLane->SpeedF = inLane->DashPoke.PokeParam.BaseSpeed+BoostSpeed[inLane->Boost-1];
		}else{
			GF_ASSERT(0 && "BoostOver");
		}
	}
	//アクションポイント加算「ダッシュ回数」
	PTFrame_AddActionPoint(	work, PTFrameGetCurrentID(work), inLane->LaneNo, ADD_TYPE_DASH, 1 );
}

//----------------------------------------------------------------------------
/**
 *	@brief	時間更新
 *
 *	@param	ptr		競技ワークポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void CountTime(PKTHLN_HURDLE_PTR ptr)
{
	int i;
	HURDLE_LANE *lane;

	//タイム加算
	ptr->GameTime++;

	for(i=0;i<HURDLE_EVENT_POKE_NUM;i++){
		lane = &ptr->Lane[i];
		if (!lane->Finished){
			//タイム加算
			ptr->MyTime++;
			break;
		}
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	記録調整　少数第一位までしか記録に残らないので、第二位以下をクリアする
 *
 *	@param	inTime		調整する記録
 *
 *	@return	time		調整された記録
 */
//-----------------------------------------------------------------------------
static int FixTime(int inTime)
{
	int time;
	int integer,decimal;

	OS_Printf("OrgTime = %d\n",inTime);

	integer = inTime/30;
	decimal = ((inTime%30) * 10) /30;

	time = (integer*30)+ ((decimal*30) / 10);

	OS_Printf("FixTime = %d\n",time);

	return time;
}

